Do not throw an exception when a when-statement with no else makes no match

This commit is contained in:
Andrey Breslav
2013-10-18 18:34:54 +04:00
parent aacf133ef6
commit ea2b6e4546
10 changed files with 111 additions and 2 deletions
@@ -3725,7 +3725,17 @@ The "returned" value of try expression with no finally is either the last expres
}
if (!hasElse && nextCondition != null) {
v.mark(nextCondition);
throwNewException(CLASS_NO_PATTERN_MATCHED_EXCEPTION);
if (!isStatement) {
// a result is expected
if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) {
// when() is supposed to be exhaustive
throwNewException(CLASS_NO_PATTERN_MATCHED_EXCEPTION);
}
else {
// non-exhaustive when() with no else -> Unit must be expected
StackValue.putUnitInstance(v);
}
}
}
markLineNumber(expression);
@@ -65,7 +65,11 @@ public final class WhenChecker {
}
}
}
return isExhaust && notEmpty;
boolean exhaustive = isExhaust && notEmpty;
if (exhaustive) {
trace.record(BindingContext.EXHAUSTIVE_WHEN, expression);
}
return exhaustive;
}
private static boolean containsEnumEntryCase(
@@ -110,6 +110,8 @@ public interface BindingContext {
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice();
WritableSlice<JetWhenExpression, Boolean> EXHAUSTIVE_WHEN = Slices.createSimpleSlice();
/**
* A scope where type of expression has been resolved
*/
@@ -0,0 +1,9 @@
fun box(): String {
var r = "OK"
val x = 3
val y: Unit = when (x) {
1 -> { r = "Fail 0" }
2 -> { r = "Fail 1" }
}
return r
}
@@ -0,0 +1,9 @@
enum class En {
A
B
}
fun box(): String = when(En.A) {
En.A -> "OK"
En.B -> "Fail 1"
}
@@ -0,0 +1,12 @@
enum class En {
A
B
}
fun box(): String {
when(En.A) {
En.A -> "s1"
En.B -> "s2"
}
return "OK"
}
@@ -0,0 +1,14 @@
enum class En {
A
B
}
fun box(): String {
val u: Unit = when(En.A) {
En.A -> {}
En.B -> {}
}
return "OK"
}
@@ -0,0 +1,11 @@
var r = "OK"
fun foo(x: Int) {
return when (x) {
1 -> { r = "Fail" }
}
}
fun box(): String {
foo(0)
return r
}
@@ -0,0 +1,8 @@
fun box(): String {
val x = 3
when (x) {
1 -> {}
2 -> {}
}
return "OK"
}
@@ -4413,16 +4413,46 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/when/noElseAssigned.kt");
}
@TestMetadata("noElseAssignedNoMatch.kt")
public void testNoElseAssignedNoMatch() throws Exception {
doTest("compiler/testData/codegen/box/when/noElseAssignedNoMatch.kt");
}
@TestMetadata("noElseExhaustive.kt")
public void testNoElseExhaustive() throws Exception {
doTest("compiler/testData/codegen/box/when/noElseExhaustive.kt");
}
@TestMetadata("noElseExhaustiveStatement.kt")
public void testNoElseExhaustiveStatement() throws Exception {
doTest("compiler/testData/codegen/box/when/noElseExhaustiveStatement.kt");
}
@TestMetadata("noElseExhaustiveUnitExpected.kt")
public void testNoElseExhaustiveUnitExpected() throws Exception {
doTest("compiler/testData/codegen/box/when/noElseExhaustiveUnitExpected.kt");
}
@TestMetadata("noElseInRetunedExpression.kt")
public void testNoElseInRetunedExpression() throws Exception {
doTest("compiler/testData/codegen/box/when/noElseInRetunedExpression.kt");
}
@TestMetadata("noElseInRetunedExpressionNoMatch.kt")
public void testNoElseInRetunedExpressionNoMatch() throws Exception {
doTest("compiler/testData/codegen/box/when/noElseInRetunedExpressionNoMatch.kt");
}
@TestMetadata("noElseInStatement.kt")
public void testNoElseInStatement() throws Exception {
doTest("compiler/testData/codegen/box/when/noElseInStatement.kt");
}
@TestMetadata("noElseNoMatch.kt")
public void testNoElseNoMatch() throws Exception {
doTest("compiler/testData/codegen/box/when/noElseNoMatch.kt");
}
@TestMetadata("nullableWhen.kt")
public void testNullableWhen() throws Exception {
doTest("compiler/testData/codegen/box/when/nullableWhen.kt");