diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 6430d55ed69..878e732ddfe 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1118,9 +1118,20 @@ public class ExpressionCodegen extends KtVisitor impleme KotlinType captureReceiver = closure.getCapturedReceiverFromOuterContext(); if (captureReceiver != null) { - StackValue capturedReceiver = - functionReferenceReceiver != null ? functionReferenceReceiver : - generateExtensionReceiver(unwrapOriginalReceiverOwnerForSuspendLambda(context)); + StackValue capturedReceiver = functionReferenceReceiver; + if (capturedReceiver == null) { + CallableDescriptor descriptor = unwrapOriginalReceiverOwnerForSuspendLambda(context); + if (descriptor.getExtensionReceiverParameter() != null) { + capturedReceiver = generateExtensionReceiver(descriptor); + } + } + if (capturedReceiver == null) { + CallableDescriptor descriptor = closure.getEnclosingCallableDescriptorWithReceiver(); + if (descriptor != null) { + capturedReceiver = generateExtensionReceiver(descriptor); + } + } + assert capturedReceiver != null : "Captured receiver is null for closure " + closure; callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CalculatedClosure.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CalculatedClosure.java index fff3f5ec340..ea4371260b2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CalculatedClosure.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CalculatedClosure.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor; import org.jetbrains.kotlin.config.LanguageVersionSettings; +import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.resolve.BindingContext; @@ -52,4 +53,7 @@ public interface CalculatedClosure { boolean isSuspend(); boolean isSuspendLambda(); + + @Nullable + CallableDescriptor getEnclosingCallableDescriptorWithReceiver(); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/MutableClosure.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/MutableClosure.java index 35948520ab8..245a4fc0084 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/MutableClosure.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/MutableClosure.java @@ -92,7 +92,9 @@ public final class MutableClosure implements CalculatedClosure { } if (captureEnclosingReceiver) { - ReceiverParameterDescriptor parameter = getEnclosingReceiverDescriptor(); + CallableDescriptor descriptor = getEnclosingCallableDescriptorWithReceiver(); + assert descriptor != null : "Receiver callable descriptor should exist"; + ReceiverParameterDescriptor parameter = descriptor.getExtensionReceiverParameter(); assert parameter != null : "Receiver parameter should exist in " + enclosingFunWithReceiverDescriptor; return parameter.getType(); } @@ -190,7 +192,8 @@ public final class MutableClosure implements CalculatedClosure { } @Nullable - public ReceiverParameterDescriptor getEnclosingReceiverDescriptor() { - return enclosingFunWithReceiverDescriptor != null ? enclosingFunWithReceiverDescriptor.getExtensionReceiverParameter() : null; + @Override + public CallableDescriptor getEnclosingCallableDescriptorWithReceiver() { + return enclosingFunWithReceiverDescriptor; } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/LocalLookup.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/LocalLookup.java index 3a8a61ff538..4c2293a12a0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/LocalLookup.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/LocalLookup.java @@ -138,7 +138,10 @@ public interface LocalLookup { MutableClosure closure, Type classType ) { - ReceiverParameterDescriptor enclosingReceiverDescriptor = closure.getEnclosingReceiverDescriptor(); + CallableDescriptor enclosingCallableWithReceiver = closure.getEnclosingCallableDescriptorWithReceiver(); + ReceiverParameterDescriptor enclosingReceiverDescriptor = + enclosingCallableWithReceiver != null ? enclosingCallableWithReceiver.getExtensionReceiverParameter() : null; + if (enclosingReceiverDescriptor != d) { return null; } diff --git a/compiler/testData/codegen/box/extensionFunctions/kt23675.kt b/compiler/testData/codegen/box/extensionFunctions/kt23675.kt new file mode 100644 index 00000000000..dfb68448f35 --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/kt23675.kt @@ -0,0 +1,25 @@ +//WITH_RUNTIME + +// IGNORE_BACKEND: JVM_IR +// IGNORE_BACKEND: JS_IR + +class Environment( + val fieldAccessedInsideChild: Int, + val how: Environment.() -> Unit +) +fun box(): String { + Environment( + 3, + { + class Child { + val a = fieldAccessedInsideChild + } + class Parent { + val children: List = + (0..4).map { Child() } + } + } + ) + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 110adcc0e24..9d95b026467 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -10616,6 +10616,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); } + @TestMetadata("kt23675.kt") + public void testKt23675() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt"); + } + @TestMetadata("kt3285.kt") public void testKt3285() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index b1d872d32e2..1a64feb078b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -10616,6 +10616,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); } + @TestMetadata("kt23675.kt") + public void testKt23675() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt"); + } + @TestMetadata("kt3285.kt") public void testKt3285() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index d93c0f477a0..433f3a52c26 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -9501,6 +9501,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); } + @TestMetadata("kt23675.kt") + public void testKt23675() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt"); + } + @TestMetadata("kt3285.kt") public void testKt3285() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt"); diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt31709.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt31709.kt new file mode 100644 index 00000000000..becf180fba4 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt31709.kt @@ -0,0 +1,13 @@ +package kt31709 + +data class A(val a: Int) + +fun main() { + with(A(2)) { + //Breakpoint! + listOf(1, 2, 3, 4, 5).filter { it > a } + } +} + +// EXPRESSION: listOf(1, 2, 3, 4, 5).filter { it > a } +// RESULT: instance of java.util.ArrayList(id=ID): Ljava/util/ArrayList; \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt31709.out b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt31709.out new file mode 100644 index 00000000000..e2671db92e7 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt31709.out @@ -0,0 +1,13 @@ +LineBreakpoint created at kt31709.kt:8 +Run Java +Connected to the target VM +kt31709.kt:8 +Compile bytecode for listOf(1, 2, 3, 4, 5).filter { it > a } +kt31709.kt:8 +resuming kt31709.kt:8 +resuming kt31709.kt:8 +resuming kt31709.kt:8 +resuming kt31709.kt:8 +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index 6463c87b557..24672eb8db9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -286,6 +286,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt29179.kt"); } + @TestMetadata("kt31709.kt") + public void testKt31709() throws Exception { + runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt31709.kt"); + } + @TestMetadata("kt5554OnlyIntsShouldBeCoerced.kt") public void testKt5554OnlyIntsShouldBeCoerced() throws Exception { runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt5554OnlyIntsShouldBeCoerced.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 5fb6c4a31c7..ee417faceec 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -8241,6 +8241,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); } + @TestMetadata("kt23675.kt") + public void testKt23675() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt"); + } + @TestMetadata("kt3285.kt") public void testKt3285() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.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 e5dd77fab3b..3ba1e479c79 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 @@ -9326,6 +9326,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); } + @TestMetadata("kt23675.kt") + public void testKt23675() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/kt23675.kt"); + } + @TestMetadata("kt3285.kt") public void testKt3285() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/kt3285.kt");