Support empty if-statements
Type-check "if (...) ;" to Unit, report "implicit cast to Unit", propagate data flow info out of its condition #KT-2478 Fixed
This commit is contained in:
@@ -357,7 +357,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
return genQualified(receiver, expression.getBaseExpression());
|
||||
}
|
||||
|
||||
private static boolean isEmptyExpression(JetElement expr) {
|
||||
private static boolean isEmptyExpression(@Nullable JetElement expr) {
|
||||
if (expr == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -383,10 +383,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
JetExpression thenExpression = expression.getThen();
|
||||
JetExpression elseExpression = expression.getElse();
|
||||
|
||||
if (thenExpression == null && elseExpression == null) {
|
||||
throw new CompilationException("Both brunches of if/else are null", null, expression);
|
||||
}
|
||||
|
||||
if (isEmptyExpression(thenExpression)) {
|
||||
if (isEmptyExpression(elseExpression)) {
|
||||
condition.put(asmType, v);
|
||||
|
||||
+5
-2
@@ -48,7 +48,9 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
@@ -108,7 +110,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
return getTypeInfoWhenOnlyOneBranchIsPresent(
|
||||
thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression, isStatement);
|
||||
}
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
return DataFlowUtils.checkImplicitCast(KotlinBuiltIns.getInstance().getUnitType(), ifExpression, contextWithExpectedType,
|
||||
isStatement, thenInfo.or(elseInfo));
|
||||
}
|
||||
if (thenBranch == null) {
|
||||
return getTypeInfoWhenOnlyOneBranchIsPresent(
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
fun box(): String {
|
||||
if (true);
|
||||
if (false);
|
||||
val iftrue = if (true);
|
||||
val iffalse = if (false);
|
||||
|
||||
var state = 0
|
||||
val k = if (state++==1);
|
||||
if (state != 1) return "Fail: $state"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
fun foo(x: Unit) = x
|
||||
|
||||
fun test() {
|
||||
if (false);
|
||||
if (true);
|
||||
|
||||
val x = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>if (false)<!>;
|
||||
foo(x)
|
||||
|
||||
val y: Unit = if (false);
|
||||
foo(y)
|
||||
|
||||
foo({if (1==1);}())
|
||||
|
||||
return if (true);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
fun f1(s: String?) {
|
||||
if (s!! == "");
|
||||
s : String
|
||||
}
|
||||
|
||||
fun f2(s: Number?) {
|
||||
if (s is Int);
|
||||
<!TYPE_MISMATCH!>s<!> : Int
|
||||
if (s as Int == 42);
|
||||
s : Int
|
||||
}
|
||||
|
||||
fun f3(s: Number?) {
|
||||
if (s is Int && s as Int == 42);
|
||||
<!TYPE_MISMATCH!>s<!> : Int
|
||||
}
|
||||
|
||||
fun f4(s: Int?) {
|
||||
var u = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>if (s!! == 42)<!>;
|
||||
if (u == Unit.VALUE) u = if (s == 239);
|
||||
return u
|
||||
}
|
||||
@@ -1565,6 +1565,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/controlStructures"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("emptyIf.kt")
|
||||
public void testEmptyIf() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/controlStructures/emptyIf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forLoopWithNullableRange.kt")
|
||||
public void testForLoopWithNullableRange() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/controlStructures/forLoopWithNullableRange.kt");
|
||||
@@ -1757,6 +1762,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
doTest("compiler/testData/diagnostics/tests/dataFlow/CalleeExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("EmptyIf.kt")
|
||||
public void testEmptyIf() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/dataFlow/EmptyIf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("IsExpression.kt")
|
||||
public void testIsExpression() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/dataFlow/IsExpression.kt");
|
||||
@@ -3917,7 +3927,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
public void testContains() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/binaryExpressions/contains.kt");
|
||||
}
|
||||
|
||||
|
||||
@TestMetadata("mathOperations.kt")
|
||||
public void testMathOperations() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inline/binaryExpressions/mathOperations.kt");
|
||||
|
||||
@@ -1427,6 +1427,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest("compiler/testData/codegen/box/controlStructures/doWhileFib.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("emptyIf.kt")
|
||||
public void testEmptyIf() throws Exception {
|
||||
doTest("compiler/testData/codegen/box/controlStructures/emptyIf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("finallyOnEmptyReturn.kt")
|
||||
public void testFinallyOnEmptyReturn() throws Exception {
|
||||
doTest("compiler/testData/codegen/box/controlStructures/finallyOnEmptyReturn.kt");
|
||||
|
||||
Reference in New Issue
Block a user