From 436c298e47b4b30e6b8883f4e8bcf70469340cb7 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 20 Feb 2012 12:14:39 +0200 Subject: [PATCH] weird bug with nested closures using outer receiver --- .../jetbrains/jet/codegen/ClosureCodegen.java | 7 ++-- .../jetbrains/jet/codegen/CodegenContext.java | 32 ++++++++++++++++++- .../jetbrains/jet/codegen/CodegenUtil.java | 16 +++++++--- .../jet/codegen/ObjectOrClosureCodegen.java | 2 +- .../codegen/extensionFunctions/nested.kt | 21 ++++++++++++ .../jet/codegen/ExtensionFunctionsTest.java | 5 +++ 6 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 compiler/testData/codegen/extensionFunctions/nested.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 0de3985a090..95b020d100d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -155,7 +155,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor); answer.addArg(valueDescriptor.getOuterValue()); } - else if(descriptor instanceof NamedFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { + else if(CodegenUtil.isNamedFun(descriptor, state.getBindingContext()) && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor); answer.addArg(valueDescriptor.getOuterValue()); } @@ -257,7 +257,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { argCount++; variableDescriptors.add(descriptor); } - else if(descriptor instanceof NamedFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { + else if(CodegenUtil.isNamedFun(descriptor, state.getBindingContext()) && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { argCount++; variableDescriptors.add(descriptor); } @@ -283,7 +283,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()); argTypes[i++] = type; } - else if(descriptor instanceof NamedFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { + else if(CodegenUtil.isNamedFun(descriptor, state.getBindingContext()) && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { final Type type = Type.getObjectType(state.getTypeMapper().classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor))); argTypes[i++] = type; } @@ -294,7 +294,6 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { if (cv.generateCode()) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); - ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state); iv.load(0, Type.getObjectType(funClass)); // expressionCodegen.generateTypeInfo(new ProjectionErasingJetType(returnType)); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index 3ee8b658e55..8edec05f39c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -44,6 +44,11 @@ public abstract class CodegenContext { public boolean isStatic() { return true; } + + @Override + public String toString() { + return "ROOT"; + } }; protected static final StackValue local0 = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); @@ -73,7 +78,7 @@ public abstract class CodegenContext { } protected abstract ClassDescriptor getThisDescriptor (); - + public DeclarationDescriptor getClassOrNamespaceDescriptor() { CodegenContext c = this; while(true) { @@ -331,6 +336,11 @@ public abstract class CodegenContext { protected StackValue getOuterExpression(StackValue prefix) { return getParentContext().getOuterExpression(prefix); } + + @Override + public String toString() { + return "Method: " + getContextDescriptor(); + } } public static class ConstructorContext extends MethodContext { @@ -346,6 +356,11 @@ public abstract class CodegenContext { protected StackValue getOuterExpression(StackValue prefix) { return outerExpression; } + + @Override + public String toString() { + return "Constructor: " + getContextDescriptor().getName(); + } } public static class ClassContext extends CodegenContext { @@ -388,6 +403,11 @@ public abstract class CodegenContext { public boolean isStatic() { return false; } + + @Override + public String toString() { + return "Anonymous: " + getThisDescriptor(); + } } public static class ClosureContext extends ReceiverContext { @@ -417,6 +437,11 @@ public abstract class CodegenContext { public boolean isStatic() { return false; } + + @Override + public String toString() { + return "Closure: " + classDescriptor; + } } public static class NamespaceContext extends CodegenContext { @@ -433,5 +458,10 @@ public abstract class CodegenContext { public boolean isStatic() { return true; } + + @Override + public String toString() { + return "Namespace: " + getContextDescriptor().getName(); + } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 868055d41cf..3ee35d6c49f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -16,12 +16,12 @@ package org.jetbrains.jet.codegen; +import com.intellij.psi.PsiElement; import gnu.trove.THashSet; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.psi.JetClassObject; -import org.jetbrains.jet.lang.psi.JetClassOrObject; -import org.jetbrains.jet.lang.psi.JetObjectDeclaration; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; @@ -144,9 +144,17 @@ public class CodegenUtil { } } - static boolean isNonLiteralObject(JetClassOrObject myClass) { + public static boolean isNonLiteralObject(JetClassOrObject myClass) { return myClass instanceof JetObjectDeclaration && !((JetObjectDeclaration) myClass).isObjectLiteral() && !(myClass.getParent() instanceof JetClassObject); } + + public static boolean isNamedFun(DeclarationDescriptor fd, BindingContext bindingContext) { + PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, fd); + if(psiElement instanceof JetNamedFunction) { + return true; + } + return false; + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java index 6db2fdcceca..4129668524a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java @@ -76,7 +76,7 @@ public class ObjectOrClosureCodegen { return innerValue; } - if(d instanceof NamedFunctionDescriptor && d.getContainingDeclaration() instanceof FunctionDescriptor) { + if(CodegenUtil.isNamedFun(d, state.getBindingContext()) && d.getContainingDeclaration() instanceof FunctionDescriptor) { FunctionDescriptor vd = (FunctionDescriptor) d; final int idx = exprContext.lookupLocal(vd); diff --git a/compiler/testData/codegen/extensionFunctions/nested.kt b/compiler/testData/codegen/extensionFunctions/nested.kt new file mode 100644 index 00000000000..afb390f614c --- /dev/null +++ b/compiler/testData/codegen/extensionFunctions/nested.kt @@ -0,0 +1,21 @@ +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.locks.ReentrantLock; + +fun Int.latch(op: CountDownLatch.() -> T) : T { + val cdl = CountDownLatch(this) + val res = cdl.op() + cdl.await() + return res +} + +fun id(op : ()->Unit) = op() + +fun box() : String { + 1.latch{ + id { + countDown() + } + } + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java b/compiler/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java index 51264cf048a..99552a8d360 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java @@ -55,6 +55,11 @@ public class ExtensionFunctionsTest extends CodegenTestCase { blackBoxFile("regressions/kt475.jet"); } + public void testKtNested() throws Exception { + createEnvironmentWithFullJdk(); + blackBoxFile("extensionFunctions/nested.kt"); + } + public void testKt865() throws Exception { createEnvironmentWithFullJdk(); blackBoxFile("regressions/kt865.jet");