Exhaustive whens without else and 'Nothing' as the result are considered 'implicit exhaustive'
This commit is contained in:
committed by
Mikhail Glukhikh
parent
d62d7dd84f
commit
b93894953d
+5
-1
@@ -145,10 +145,11 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isExhaustive = WhenChecker.isWhenExhaustive(expression, context.trace);
|
||||||
if (commonDataFlowInfo == null) {
|
if (commonDataFlowInfo == null) {
|
||||||
commonDataFlowInfo = context.dataFlowInfo;
|
commonDataFlowInfo = context.dataFlowInfo;
|
||||||
}
|
}
|
||||||
else if (expression.getElseExpression() == null && !WhenChecker.isWhenExhaustive(expression, context.trace)) {
|
else if (expression.getElseExpression() == null && !isExhaustive) {
|
||||||
// Without else expression in non-exhaustive when, we *must* take initial data flow info into account,
|
// Without else expression in non-exhaustive when, we *must* take initial data flow info into account,
|
||||||
// because data flow can bypass all when branches in this case
|
// because data flow can bypass all when branches in this case
|
||||||
commonDataFlowInfo = commonDataFlowInfo.or(context.dataFlowInfo);
|
commonDataFlowInfo = commonDataFlowInfo.or(context.dataFlowInfo);
|
||||||
@@ -158,6 +159,9 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (resultType != null) {
|
if (resultType != null) {
|
||||||
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(expression, resultType, context);
|
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(expression, resultType, context);
|
||||||
commonDataFlowInfo = commonDataFlowInfo.assign(resultValue, whenValue);
|
commonDataFlowInfo = commonDataFlowInfo.assign(resultValue, whenValue);
|
||||||
|
if (isExhaustive && expression.getElseExpression() == null && KotlinBuiltIns.isNothing(resultType)) {
|
||||||
|
context.trace.record(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, expression);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return TypeInfoFactoryKt.createTypeInfo(expressionTypes.isEmpty() ? null : components.dataFlowAnalyzer.checkType(
|
return TypeInfoFactoryKt.createTypeInfo(expressionTypes.isEmpty() ? null : components.dataFlowAnalyzer.checkType(
|
||||||
components.dataFlowAnalyzer.checkImplicitCast(
|
components.dataFlowAnalyzer.checkImplicitCast(
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import enum.HappyEnum
|
|||||||
import enum.HappyEnum.*
|
import enum.HappyEnum.*
|
||||||
|
|
||||||
fun f(e: HappyEnum) {
|
fun f(e: HappyEnum) {
|
||||||
when (e) {
|
<!DEBUG_INFO_IMPLICIT_EXHAUSTIVE!>when (e) {
|
||||||
CASE1 -> throw UnsupportedOperationException() // unresolved reference
|
CASE1 -> throw UnsupportedOperationException() // unresolved reference
|
||||||
CASE2 -> throw UnsupportedOperationException() // unresolved references
|
CASE2 -> throw UnsupportedOperationException() // unresolved references
|
||||||
}
|
}<!>
|
||||||
}
|
}
|
||||||
+2
-2
@@ -4,10 +4,10 @@ sealed class Tree {
|
|||||||
class Node(val left: Tree, val right: Tree): Tree()
|
class Node(val left: Tree, val right: Tree): Tree()
|
||||||
|
|
||||||
fun max(): Int {
|
fun max(): Int {
|
||||||
when(this) {
|
<!DEBUG_INFO_IMPLICIT_EXHAUSTIVE!>when(this) {
|
||||||
is Empty -> return -1
|
is Empty -> return -1
|
||||||
is Leaf -> return <!DEBUG_INFO_SMARTCAST!>this<!>.x
|
is Leaf -> return <!DEBUG_INFO_SMARTCAST!>this<!>.x
|
||||||
is Node -> return <!DEBUG_INFO_SMARTCAST!>this<!>.left.max()
|
is Node -> return <!DEBUG_INFO_SMARTCAST!>this<!>.left.max()
|
||||||
}
|
}<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ enum class Color { RED, GREEN, BLUE }
|
|||||||
|
|
||||||
fun foo(arr: Array<Color>): Color {
|
fun foo(arr: Array<Color>): Color {
|
||||||
loop@ for (color in arr) {
|
loop@ for (color in arr) {
|
||||||
when (color) {
|
<!DEBUG_INFO_IMPLICIT_EXHAUSTIVE!>when (color) {
|
||||||
Color.RED -> return color
|
Color.RED -> return color
|
||||||
Color.GREEN -> break@loop
|
Color.GREEN -> break@loop
|
||||||
Color.BLUE -> if (arr.size == 1) return color else continue@loop
|
Color.BLUE -> if (arr.size == 1) return color else continue@loop
|
||||||
}
|
}<!>
|
||||||
// Unreachable
|
// Unreachable
|
||||||
<!UNREACHABLE_CODE!>return Color.BLUE<!>
|
<!UNREACHABLE_CODE!>return Color.BLUE<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -13,8 +13,8 @@ public enum J {
|
|||||||
// FILE: K.kt
|
// FILE: K.kt
|
||||||
|
|
||||||
fun foo(): Int {
|
fun foo(): Int {
|
||||||
when (<!WHEN_ENUM_CAN_BE_NULL_IN_JAVA!>J.create()<!>) {
|
<!DEBUG_INFO_IMPLICIT_EXHAUSTIVE!>when (<!WHEN_ENUM_CAN_BE_NULL_IN_JAVA!>J.create()<!>) {
|
||||||
J.A -> return 1
|
J.A -> return 1
|
||||||
J.B -> return 2
|
J.B -> return 2
|
||||||
}
|
}<!>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ enum class Direction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun foo(dir: Direction): Int {
|
fun foo(dir: Direction): Int {
|
||||||
when (dir) {
|
<!DEBUG_INFO_IMPLICIT_EXHAUSTIVE!>when (dir) {
|
||||||
Direction.NORTH -> return 1
|
Direction.NORTH -> return 1
|
||||||
Direction.SOUTH -> return 2
|
Direction.SOUTH -> return 2
|
||||||
Direction.WEST -> return 3
|
Direction.WEST -> return 3
|
||||||
Direction.EAST -> return 4
|
Direction.EAST -> return 4
|
||||||
}
|
}<!>
|
||||||
// See KT-1882: no return is needed at the end
|
// See KT-1882: no return is needed at the end
|
||||||
}
|
}
|
||||||
@@ -3,12 +3,12 @@ enum class Direction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun foo(dir: Direction): Int {
|
fun foo(dir: Direction): Int {
|
||||||
when (dir) {
|
<!DEBUG_INFO_IMPLICIT_EXHAUSTIVE!>when (dir) {
|
||||||
Direction.NORTH -> return 1
|
Direction.NORTH -> return 1
|
||||||
Direction.SOUTH -> throw AssertionError("!!!")
|
Direction.SOUTH -> throw AssertionError("!!!")
|
||||||
Direction.WEST -> return 3
|
Direction.WEST -> return 3
|
||||||
Direction.EAST -> return 4
|
Direction.EAST -> return 4
|
||||||
}
|
}<!>
|
||||||
// Error: Unreachable code. Return is not required.
|
// Error: Unreachable code. Return is not required.
|
||||||
<!UNREACHABLE_CODE!>if (dir == Direction.SOUTH) return 2<!>
|
<!UNREACHABLE_CODE!>if (dir == Direction.SOUTH) return 2<!>
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user