diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java index d4bc4763448..46345c0039d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java @@ -309,9 +309,9 @@ public class AsmUtil { null); } - ClassifierDescriptor captureReceiver = closure.getCaptureReceiver(); - if (captureReceiver != null) { - v.newField(null, access, CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiver).getDescriptor(), + JetType captureReceiverType = closure.getCaptureReceiverType(); + if (captureReceiverType != null) { + v.newField(null, access, CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiverType).getDescriptor(), null, null); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index ad422f87e13..5f8cc28469d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -249,9 +249,9 @@ public class ClosureCodegen extends ParentCodegenAwareImpl { Type type = typeMapper.mapType(captureThis); args.add(FieldInfo.createForHiddenField(ownerType, type, CAPTURED_THIS_FIELD)); } - ClassifierDescriptor captureReceiver = closure.getCaptureReceiver(); - if (captureReceiver != null) { - args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiver), CAPTURED_RECEIVER_FIELD)); + JetType captureReceiverType = closure.getCaptureReceiverType(); + if (captureReceiverType != null) { + args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiverType), CAPTURED_RECEIVER_FIELD)); } for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) { @@ -268,7 +268,7 @@ public class ClosureCodegen extends ParentCodegenAwareImpl { args.add(FieldInfo.createForHiddenField(ownerType, classType, "$" + descriptor.getName().asString())); } else if (descriptor instanceof FunctionDescriptor) { - assert captureReceiver != null; + assert captureReceiverType != null; } } return args; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 38753e4e0cf..3c20f02426d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -129,7 +129,7 @@ public class CodegenUtil { } public static boolean isConst(CalculatedClosure closure) { - return closure.getCaptureThis() == null && closure.getCaptureReceiver() == null && closure.getCaptureVariables().isEmpty(); + return closure.getCaptureThis() == null && closure.getCaptureReceiverType() == null && closure.getCaptureVariables().isEmpty(); } public static T peekFromStack(Stack stack) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 00328baf75a..db167226987 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1374,9 +1374,9 @@ public class ExpressionCodegen extends JetVisitor implem generateThisOrOuter(captureThis, false).put(OBJECT_TYPE, v); } - ClassifierDescriptor captureReceiver = closure.getCaptureReceiver(); + JetType captureReceiver = closure.getCaptureReceiverType(); if (captureReceiver != null) { - v.load(context.isStatic() ? 0 : 1, typeMapper.mapClass(captureReceiver)); + v.load(context.isStatic() ? 0 : 1, typeMapper.mapType(captureReceiver)); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CalculatedClosure.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CalculatedClosure.java index 4c24911536e..b1c680779c6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CalculatedClosure.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CalculatedClosure.java @@ -22,9 +22,9 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.asm4.Type; import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall; +import org.jetbrains.jet.lang.types.JetType; import java.util.List; import java.util.Map; @@ -41,7 +41,7 @@ public interface CalculatedClosure { ClassDescriptor getCaptureThis(); @Nullable - ClassifierDescriptor getCaptureReceiver(); + JetType getCaptureReceiverType(); @NotNull Map getCaptureVariables(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/MutableClosure.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/MutableClosure.java index 7e1787c53b7..50b3e4941ac 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/MutableClosure.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/MutableClosure.java @@ -23,9 +23,10 @@ import org.jetbrains.asm4.Type; import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall; +import org.jetbrains.jet.lang.types.JetType; import java.util.*; @@ -72,10 +73,14 @@ public final class MutableClosure implements CalculatedClosure { } @Override - public ClassifierDescriptor getCaptureReceiver() { - return captureReceiver - ? enclosingReceiverDescriptor.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor() - : null; + public JetType getCaptureReceiverType() { + if (captureReceiver) { + ReceiverParameterDescriptor parameter = enclosingReceiverDescriptor.getReceiverParameter(); + assert parameter != null : "Receiver parameter should exist in " + enclosingReceiverDescriptor; + return parameter.getType(); + } + + return null; } public void setCaptureReceiver() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 38186e411d6..d62248fcd90 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -812,10 +812,10 @@ public class JetTypeMapper extends BindingTraceAware { signatureWriter.writeParameterTypeEnd(); } - ClassifierDescriptor captureReceiver = closure != null ? closure.getCaptureReceiver() : null; - if (captureReceiver != null) { + JetType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null; + if (captureReceiverType != null) { signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER); - mapType(captureReceiver.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE); + mapType(captureReceiverType, signatureWriter, JetTypeMapperMode.VALUE); signatureWriter.writeParameterTypeEnd(); } diff --git a/compiler/testData/codegen/box/extensionFunctions/kt4118.kt b/compiler/testData/codegen/box/extensionFunctions/kt4118.kt new file mode 100644 index 00000000000..e7293b8ca3a --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/kt4118.kt @@ -0,0 +1,94 @@ +fun Array.test1(): Array { + val func = {(i:Int) -> this} + return func(1) +} + +fun Array.test1Nested(): Array { + val func = {(i:Int) -> { this }()} + return func(1) +} + + +fun Array.test2() : Array { + class Z2() { + fun run(): Array { + this@test2 + } + } + return Z2().run() +} + +fun Array.test2Nested() : Array { + class Z2() { + fun run(): Array { + class Z3 { + fun run(): Array { + return this@test2Nested; + } + } + return Z3().run() + } + } + return Z2().run() +} + +fun Array.test3(): Array { + fun local(): Array { + this@test3 + } + return local() +} + +fun Array.test3Nested(): Array { + fun local(): Array { + fun local2(): Array { + this@test3Nested + } + return local2() + } + return local() +} + + +fun Array.test4() : Array { + return object { + fun run() : Array { + return this@test4 + } + }.run() +} + +fun Array.test4Nested() : Array { + return object { + fun run() : Array { + return object { + fun run() : Array { + return this@test4Nested + } + }.run() + } + }.run() +} + +fun Array.test1(): Array { + val func = {(i:Int) -> this} + return func(1) +} + + +fun box() : String { + val array = Array(2, { i -> "${i}" }) + if (array != array.test1()) return "fail 1" + if (array != array.test2()) return "fail 2" + if (array != array.test3()) return "fail 3" + if (array != array.test4()) return "fail 4" + + if (array != array.test1Nested()) return "fail 1Nested" + if (array != array.test2Nested()) return "fail 2Nested" + if (array != array.test3Nested()) return "fail 3Nested" + if (array != array.test4Nested()) return "fail 4Nested" + + val array2 = Array(2, { i -> DoubleArray(i) }) + if (array2 != array2.test1()) return "fail on array of double []" + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 9548b9716f6..73317b40af1 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -2109,6 +2109,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/extensionFunctions/kt1953_class.kt"); } + @TestMetadata("kt4118.kt") + public void testKt4118() throws Exception { + doTest("compiler/testData/codegen/box/extensionFunctions/kt4118.kt"); + } + @TestMetadata("kt475.kt") public void testKt475() throws Exception { doTest("compiler/testData/codegen/box/extensionFunctions/kt475.kt");