diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index b48060b7b0e..11dbb103f1e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -146,7 +146,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { if (enclosingType == null) captureThis = null; - final Method constructor = generateConstructor(funClass, fun); + final Method constructor = generateConstructor(funClass, fun, funDescriptor); if (captureThis != null) { cv.newField(fun, ACC_FINAL, "this$0", enclosingType.getDescriptor(), null, null); @@ -160,6 +160,9 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis, captureReceiver); for (DeclarationDescriptor descriptor : closure.keySet()) { + if (descriptor == funDescriptor) { + continue; + } if (descriptor instanceof VariableDescriptor) { final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor); answer.addArg(valueDescriptor.getOuterValue()); @@ -253,13 +256,16 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { } } - private Method generateConstructor(JvmClassName funClass, PsiElement fun) { + private Method generateConstructor(JvmClassName funClass, JetExpression fun, FunctionDescriptor funDescriptor) { int argCount = captureThis != null ? 1 : 0; argCount += (captureReceiver != null ? 1 : 0); ArrayList variableDescriptors = new ArrayList(); for (DeclarationDescriptor descriptor : closure.keySet()) { + if (descriptor == funDescriptor) { + continue; + } if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) { argCount++; variableDescriptors.add(descriptor); @@ -284,7 +290,13 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { argTypes[i++] = captureReceiver; } + boolean putFieldForMyself = false; + for (DeclarationDescriptor descriptor : closure.keySet()) { + if (descriptor == funDescriptor) { + putFieldForMyself = true; + continue; + } if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) { final Type sharedVarType = state.getInjector().getJetTypeMapper().getSharedVarType(descriptor); final Type type; @@ -336,6 +348,14 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { StackValue.field(type, name, fieldName, false).store(type, iv); } + if (putFieldForMyself) { + Type type = name.getAsmType(); + String fieldName = "$" + funDescriptor.getName(); + iv.load(0, type); + iv.dup(); + StackValue.field(type, name, fieldName, false).store(type, iv); + } + iv.visitInsn(RETURN); FunctionCodegen.endVisit(iv, "constructor", fun); diff --git a/compiler/testData/codegen/classes/recursiveClosure.kt b/compiler/testData/codegen/classes/recursiveClosure.kt new file mode 100644 index 00000000000..056ed013324 --- /dev/null +++ b/compiler/testData/codegen/classes/recursiveClosure.kt @@ -0,0 +1,7 @@ +fun foo(s: String): String { + fun bar(count: Int): String = + if (count == 0) s else bar(count - 1) + return bar(239) +} + +fun box(): String = foo("OK") diff --git a/compiler/testData/codegen/regressions/kt2280.kt b/compiler/testData/codegen/regressions/kt2280.kt new file mode 100644 index 00000000000..79debb72bdf --- /dev/null +++ b/compiler/testData/codegen/regressions/kt2280.kt @@ -0,0 +1,7 @@ +fun box(): String { + fun rmrf(i: Int) { + if (i > 0) rmrf(i - 1) + } + rmrf(5) + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java index f019809526d..e05a3aa7706 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java @@ -66,4 +66,8 @@ public class ClosuresGenTest extends CodegenTestCase { public void testKt2151() { blackBoxFile("regressions/kt2151.kt"); } + + public void testRecursiveClosure() { + blackBoxFile("classes/recursiveClosure.kt"); + } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java index 0d1fbf7aed5..d912113456b 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java @@ -125,6 +125,10 @@ public class FunctionGenTest extends CodegenTestCase { blackBoxFile("regressions/kt2481.kt"); } + public void testKt2280() { + blackBoxFile("regressions/kt2280.kt"); + } + public static class WithJavaFunctionGenTest extends CodegenTestCase { private void blackBoxFileWithJava(@NotNull String ktFile) throws Exception { File javaClassesTempDirectory = new File(FileUtil.getTempDirectory(), "java-classes");