diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 47490fb6436..65bc5ee9729 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1086,11 +1086,15 @@ public class ExpressionCodegen extends KtVisitor impleme } for (Map.Entry entry : closure.getCaptureVariables().entrySet()) { - Type sharedVarType = typeMapper.getSharedVarType(entry.getKey()); + DeclarationDescriptor declarationDescriptor = entry.getKey(); + EnclosedValueDescriptor valueDescriptor = entry.getValue(); + + Type sharedVarType = typeMapper.getSharedVarType(declarationDescriptor); + boolean asSharedVar = sharedVarType != null; if (sharedVarType == null) { - sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey()); + sharedVarType = typeMapper.mapType((VariableDescriptor) declarationDescriptor); } - StackValue capturedVar = lookupOuterValue(entry.getValue()); + StackValue capturedVar = lookupOuterValue(valueDescriptor, asSharedVar); callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++); } @@ -1144,11 +1148,16 @@ public class ExpressionCodegen extends KtVisitor impleme } @NotNull - public StackValue lookupOuterValue(EnclosedValueDescriptor d) { + private StackValue lookupOuterValue(EnclosedValueDescriptor d, boolean asSharedVar) { DeclarationDescriptor descriptor = d.getDescriptor(); for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) { if (aCase.isCase(descriptor)) { - return aCase.outerValue(d, this); + StackValue outerValue = aCase.outerValue(d, this); + if (asSharedVar && outerValue instanceof StackValue.FieldForSharedVar) { + StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) outerValue; + return fieldForSharedVar.receiver; + } + return outerValue; } } throw new IllegalStateException("Can't get outer value in " + this + " for " + d); diff --git a/compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass1.kt b/compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass1.kt new file mode 100644 index 00000000000..2200b560d4a --- /dev/null +++ b/compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass1.kt @@ -0,0 +1,12 @@ +fun box(): String { + var x = "" + + class CapturesX { + override fun toString() = x + } + + fun localFun() = CapturesX() + + x = "OK" + return localFun().toString() +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass2.kt b/compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass2.kt new file mode 100644 index 00000000000..b3553b16847 --- /dev/null +++ b/compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass2.kt @@ -0,0 +1,15 @@ +fun box(): String { + var x = "" + + class CapturesX { + override fun toString() = x + } + + fun outerFun1(): CapturesX { + fun localFun() = CapturesX() + return localFun() + } + + x = "OK" + return outerFun1().toString() +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass3.kt b/compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass3.kt new file mode 100644 index 00000000000..e15eba1b081 --- /dev/null +++ b/compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass3.kt @@ -0,0 +1,14 @@ +fun box(): String { + var x = "" + + class CapturesX { + override fun toString() = x + } + + class LocalClass { + fun foo() = CapturesX() + } + + x = "OK" + return LocalClass().foo().toString() +} \ 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 4596b1f4f51..7a091cc73c8 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 @@ -11306,6 +11306,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("recaptureVarCapturedInLocalClass1.kt") + public void testRecaptureVarCapturedInLocalClass1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass1.kt"); + doTest(fileName); + } + + @TestMetadata("recaptureVarCapturedInLocalClass2.kt") + public void testRecaptureVarCapturedInLocalClass2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass2.kt"); + doTest(fileName); + } + + @TestMetadata("recaptureVarCapturedInLocalClass3.kt") + public void testRecaptureVarCapturedInLocalClass3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass3.kt"); + doTest(fileName); + } + @TestMetadata("subclassingExtensionReceiverClass.kt") public void testSubclassingExtensionReceiverClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/subclassingExtensionReceiverClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 55ff62ab07e..805f3a5bcc4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11306,6 +11306,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("recaptureVarCapturedInLocalClass1.kt") + public void testRecaptureVarCapturedInLocalClass1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass1.kt"); + doTest(fileName); + } + + @TestMetadata("recaptureVarCapturedInLocalClass2.kt") + public void testRecaptureVarCapturedInLocalClass2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass2.kt"); + doTest(fileName); + } + + @TestMetadata("recaptureVarCapturedInLocalClass3.kt") + public void testRecaptureVarCapturedInLocalClass3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass3.kt"); + doTest(fileName); + } + @TestMetadata("subclassingExtensionReceiverClass.kt") public void testSubclassingExtensionReceiverClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/subclassingExtensionReceiverClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 2a6c275aa94..b8d1dab7038 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11318,6 +11318,24 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("recaptureVarCapturedInLocalClass1.kt") + public void testRecaptureVarCapturedInLocalClass1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass1.kt"); + doTest(fileName); + } + + @TestMetadata("recaptureVarCapturedInLocalClass2.kt") + public void testRecaptureVarCapturedInLocalClass2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass2.kt"); + doTest(fileName); + } + + @TestMetadata("recaptureVarCapturedInLocalClass3.kt") + public void testRecaptureVarCapturedInLocalClass3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass3.kt"); + doTest(fileName); + } + @TestMetadata("withclosure.kt") public void testWithclosure() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/withclosure.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 3937bd793c1..590b8cc498d 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -12512,6 +12512,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("recaptureVarCapturedInLocalClass1.kt") + public void testRecaptureVarCapturedInLocalClass1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass1.kt"); + doTest(fileName); + } + + @TestMetadata("recaptureVarCapturedInLocalClass2.kt") + public void testRecaptureVarCapturedInLocalClass2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass2.kt"); + doTest(fileName); + } + + @TestMetadata("recaptureVarCapturedInLocalClass3.kt") + public void testRecaptureVarCapturedInLocalClass3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/recaptureVarCapturedInLocalClass3.kt"); + doTest(fileName); + } + @TestMetadata("subclassingExtensionReceiverClass.kt") public void testSubclassingExtensionReceiverClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/subclassingExtensionReceiverClass.kt");