don't generate direct increment and similar bytecodes for variables which are captured in closure (KT-1980)

This commit is contained in:
Dmitry Jemerov
2012-06-02 22:41:37 +02:00
parent ba9c3d73e7
commit 58c7c7aea1
4 changed files with 47 additions and 10 deletions
@@ -1635,6 +1635,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public int indexOfLocal(JetReferenceExpression lhs) {
final DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, lhs);
if (typeMapper.isVarCapturedInClosure(declarationDescriptor)) {
return -1;
}
return lookupLocal(declarationDescriptor);
}
@@ -1033,17 +1033,17 @@ public class JetTypeMapper {
else if (descriptor instanceof FunctionDescriptor) {
return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType(), MapTypeMode.VALUE));
}
else if (descriptor instanceof VariableDescriptor) {
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
Boolean aBoolean = bindingContext.get(BindingContext.CAPTURED_IN_CLOSURE, variableDescriptor);
if (aBoolean != null && aBoolean && variableDescriptor.isVar()) {
JetType outType = variableDescriptor.getType();
return StackValue.sharedTypeForType(mapType(outType, MapTypeMode.VALUE));
}
else {
return null;
}
else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(descriptor)) {
JetType outType = ((VariableDescriptor) descriptor).getType();
return StackValue.sharedTypeForType(mapType(outType, MapTypeMode.VALUE));
}
return null;
}
public boolean isVarCapturedInClosure(DeclarationDescriptor descriptor) {
if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false;
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
Boolean aBoolean = bindingContext.get(BindingContext.CAPTURED_IN_CLOSURE, variableDescriptor);
return aBoolean != null && aBoolean && variableDescriptor.isVar();
}
}
@@ -0,0 +1,29 @@
import java.util.*
public inline fun Int.times(body : () -> Unit) {
var count = this;
while (count > 0) {
body()
count--
}
}
fun calc() : Int {
val a = ArrayList<()->Int>()
2.times {
var j = 1
a.add({ j })
++j
}
var sum = 0
for (f in a) {
val g = f as () -> Int
sum += g()
}
return sum
}
fun box() : String {
val x = calc()
return if (x == 4) "OK" else x.toString()
}
@@ -391,4 +391,9 @@ public class ClassGenTest extends CodegenTestCase {
createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS);
blackBoxFile("regressions/kt1918.kt");
}
public void testKt1980() throws Exception {
createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS);
blackBoxFile("regressions/kt1980.kt");
}
}