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
// The result is stored to local variable
protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) {
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + elementType.getDescriptor(), false);
v.store(varToStore, elementType);
protected void generateRangeOrProgressionProperty(
@NotNull Type loopRangeType,
@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 {
protected int endVar;
private StackValue loopParameter;
private AbstractForInProgressionOrRangeLoopGenerator(@NotNull KtForExpression forExpression) {
super(forExpression);
@@ -949,8 +957,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
protected void checkPostCondition(@NotNull Label loopExit) {
assert endVar != -1 :
"endVar must be allocated, endVar = " + endVar;
v.load(loopParameterVar, asmElementType);
loopParameter().put(asmElementType, v);
v.load(endVar, asmElementType);
if (asmElementType.getSort() == Type.LONG) {
v.lcmp();
@@ -964,6 +971,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override
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 {
@@ -982,8 +997,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override
public void checkEmptyLoop(@NotNull Label loopExit) {
v.load(loopParameterVar, asmElementType);
loopParameter().put(asmElementType, v);
v.load(endVar, asmElementType);
if (asmElementType.getSort() == Type.LONG) {
v.lcmp();
@@ -1002,13 +1016,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
protected void increment(@NotNull Label loopExit) {
checkPostCondition(loopExit);
if (asmElementType == Type.INT_TYPE) {
if (loopParameterType == Type.INT_TYPE) {
v.iinc(loopParameterVar, 1);
}
else {
v.load(loopParameterVar, asmElementType);
StackValue loopParameter = loopParameter();
loopParameter.put(asmElementType, 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
protected void storeRangeStartAndEnd() {
gen(rangeCall.left, asmElementType);
v.store(loopParameterVar, asmElementType);
gen(rangeCall.left, loopParameterType);
v.store(loopParameterVar, loopParameterType);
gen(rangeCall.right, asmElementType);
v.store(endVar, asmElementType);
@@ -1048,8 +1063,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.dup();
// ranges inherit first and last from corresponding progressions
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar);
}
}
@@ -1080,15 +1095,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.dup();
v.dup();
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementType, incrementVar);
}
@Override
public void checkEmptyLoop(@NotNull Label loopExit) {
v.load(loopParameterVar, asmElementType);
loopParameter().put(asmElementType, v);
v.load(endVar, asmElementType);
v.load(incrementVar, incrementType);
@@ -1133,7 +1147,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
protected void increment(@NotNull Label loopExit) {
checkPostCondition(loopExit);
v.load(loopParameterVar, asmElementType);
StackValue loopParameter = loopParameter();
loopParameter.put(asmElementType, v);
v.load(incrementVar, asmElementType);
v.add(asmElementType);
@@ -1141,7 +1156,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
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);
}
}
@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")