Fix for KT-12582: "VerifyError: Bad local variable type" caused by explicit loop variable type

#KT-12582 Fixed
This commit is contained in:
Mikhael Bogdanov
2016-06-02 11:21:30 +03:00
parent e7f9d3417f
commit a6cf169646
5 changed files with 98 additions and 21 deletions
@@ -766,9 +766,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// This method consumes range/progression from stack // This method consumes range/progression from stack
// The result is stored to local variable // The result is stored to local variable
protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) { protected void generateRangeOrProgressionProperty(
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + elementType.getDescriptor(), false); @NotNull Type loopRangeType,
v.store(varToStore, elementType); @NotNull String getterName,
@NotNull Type getterReturnType,
@NotNull Type varType,
int varToStore
) {
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + getterReturnType.getDescriptor(), false);
StackValue.local(varToStore, varType).store(StackValue.onStack(getterReturnType), v);
} }
} }
@@ -923,6 +929,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator { private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator {
protected int endVar; protected int endVar;
private StackValue loopParameter;
private AbstractForInProgressionOrRangeLoopGenerator(@NotNull KtForExpression forExpression) { private AbstractForInProgressionOrRangeLoopGenerator(@NotNull KtForExpression forExpression) {
super(forExpression); super(forExpression);
@@ -949,8 +957,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
protected void checkPostCondition(@NotNull Label loopExit) { protected void checkPostCondition(@NotNull Label loopExit) {
assert endVar != -1 : assert endVar != -1 :
"endVar must be allocated, endVar = " + endVar; "endVar must be allocated, endVar = " + endVar;
loopParameter().put(asmElementType, v);
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType); v.load(endVar, asmElementType);
if (asmElementType.getSort() == Type.LONG) { if (asmElementType.getSort() == Type.LONG) {
v.lcmp(); v.lcmp();
@@ -964,6 +971,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override @Override
public void checkPreCondition(@NotNull Label loopExit) { public void checkPreCondition(@NotNull Label loopExit) {
} }
@NotNull
protected StackValue loopParameter() {
if (loopParameter == null) {
loopParameter = StackValue.local(loopParameterVar, loopParameterType);
}
return loopParameter;
}
} }
private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator { private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator {
@@ -982,8 +997,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override @Override
public void checkEmptyLoop(@NotNull Label loopExit) { public void checkEmptyLoop(@NotNull Label loopExit) {
loopParameter().put(asmElementType, v);
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType); v.load(endVar, asmElementType);
if (asmElementType.getSort() == Type.LONG) { if (asmElementType.getSort() == Type.LONG) {
v.lcmp(); v.lcmp();
@@ -1002,13 +1016,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
protected void increment(@NotNull Label loopExit) { protected void increment(@NotNull Label loopExit) {
checkPostCondition(loopExit); checkPostCondition(loopExit);
if (asmElementType == Type.INT_TYPE) { if (loopParameterType == Type.INT_TYPE) {
v.iinc(loopParameterVar, 1); v.iinc(loopParameterVar, 1);
} }
else { else {
v.load(loopParameterVar, asmElementType); StackValue loopParameter = loopParameter();
loopParameter.put(asmElementType, v);
genIncrement(asmElementType, 1, v); genIncrement(asmElementType, 1, v);
v.store(loopParameterVar, asmElementType); loopParameter.store(StackValue.onStack(asmElementType), v);
} }
} }
} }
@@ -1026,8 +1041,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override @Override
protected void storeRangeStartAndEnd() { protected void storeRangeStartAndEnd() {
gen(rangeCall.left, asmElementType); gen(rangeCall.left, loopParameterType);
v.store(loopParameterVar, asmElementType); v.store(loopParameterVar, loopParameterType);
gen(rangeCall.right, asmElementType); gen(rangeCall.right, asmElementType);
v.store(endVar, asmElementType); v.store(endVar, asmElementType);
@@ -1048,8 +1063,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.dup(); v.dup();
// ranges inherit first and last from corresponding progressions // ranges inherit first and last from corresponding progressions
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar); generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar); generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar);
} }
} }
@@ -1080,15 +1095,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.dup(); v.dup();
v.dup(); v.dup();
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar); generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar); generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementVar); generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementType, incrementVar);
} }
@Override @Override
public void checkEmptyLoop(@NotNull Label loopExit) { public void checkEmptyLoop(@NotNull Label loopExit) {
loopParameter().put(asmElementType, v);
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType); v.load(endVar, asmElementType);
v.load(incrementVar, incrementType); v.load(incrementVar, incrementType);
@@ -1133,7 +1147,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
protected void increment(@NotNull Label loopExit) { protected void increment(@NotNull Label loopExit) {
checkPostCondition(loopExit); checkPostCondition(loopExit);
v.load(loopParameterVar, asmElementType); StackValue loopParameter = loopParameter();
loopParameter.put(asmElementType, v);
v.load(incrementVar, asmElementType); v.load(incrementVar, asmElementType);
v.add(asmElementType); v.add(asmElementType);
@@ -1141,7 +1156,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
StackValue.coerce(Type.INT_TYPE, asmElementType, v); StackValue.coerce(Type.INT_TYPE, asmElementType, v);
} }
v.store(loopParameterVar, asmElementType); loopParameter.store(StackValue.onStack(asmElementType), v);
} }
} }
@@ -0,0 +1,12 @@
fun box(): String {
var result = 0
val intRange: IntProgression = 1..3
for (i: Int? in intRange) {
result = sum(result, i)
}
return if (result == 6) "OK" else "fail: $result"
}
fun sum(i: Int, z: Int?): Int {
return i + z!!
}
@@ -0,0 +1,12 @@
fun box(): String {
var result = 0
val intRange = 1..3
for (i: Int? in intRange) {
result = sum(result, i)
}
return if (result == 6) "OK" else "fail: $result"
}
fun sum(i: Int, z: Int?): Int {
return i + z!!
}
@@ -0,0 +1,11 @@
fun box(): String {
var result = 0
for (i: Int? in 1..3) {
result = sum(result, i)
}
return if (result == 6) "OK" else "fail: $result"
}
fun sum(i: Int, z: Int?): Int {
return i + z!!
}
@@ -10668,6 +10668,33 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName); doTest(fileName);
} }
} }
@TestMetadata("compiler/testData/codegen/box/ranges/nullableLoopParameter")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NullableLoopParameter extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInNullableLoopParameter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/nullableLoopParameter"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("progressionExpression.kt")
public void testProgressionExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/nullableLoopParameter/progressionExpression.kt");
doTest(fileName);
}
@TestMetadata("rangeExpression.kt")
public void testRangeExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeExpression.kt");
doTest(fileName);
}
@TestMetadata("rangeLiteral.kt")
public void testRangeLiteral() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeLiteral.kt");
doTest(fileName);
}
}
} }
@TestMetadata("compiler/testData/codegen/box/reflection") @TestMetadata("compiler/testData/codegen/box/reflection")