diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt index cc1d5bdc72b..aea913189bd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt @@ -72,12 +72,11 @@ private object NullMissingCase : WhenMissingCase { override val branchConditionText = "null" } -private object WhenOnNullableExhaustivenessChecker : WhenExhaustivenessChecker { - override fun getMissingCases(expression: KtWhenExpression, context: BindingContext, subjectDescriptor: ClassDescriptor?, nullable: Boolean) = +// It's not a regular exhaustiveness checker, invoke it only inside other checkers +private object WhenOnNullableExhaustivenessChecker /* : WhenExhaustivenessChecker*/ { + fun getMissingCases(expression: KtWhenExpression, context: BindingContext, subjectDescriptor: ClassDescriptor?, nullable: Boolean) = if (nullable) getNullCaseIfMissing(expression, context) else listOf() - override fun isApplicable(subjectType: KotlinType): Boolean = TypeUtils.isNullableType(subjectType) - private fun getNullCaseIfMissing(expression: KtWhenExpression, context: BindingContext): List { for (entry in expression.entries) { for (condition in entry.conditions) { @@ -121,7 +120,8 @@ private object WhenOnBooleanExhaustivenessChecker : WhenExhaustivenessChecker { } } return (if (!containsTrue) listOf(BooleanMissingCase(true)) else listOf()) + - (if (!containsFalse) listOf(BooleanMissingCase(false)) else listOf()) + (if (!containsFalse) listOf(BooleanMissingCase(false)) else listOf()) + + WhenOnNullableExhaustivenessChecker.getMissingCases(expression, context, subjectDescriptor, nullable) } override fun isApplicable(subjectType: KotlinType): Boolean { @@ -210,7 +210,8 @@ private object WhenOnEnumExhaustivenessChecker : WhenOnClassExhaustivenessChecke .filter { isEnumEntry(it) } .filterIsInstance() .toSet() - return getMissingClassCases(expression, entryDescriptors, context) + return getMissingClassCases(expression, entryDescriptors, context) + + WhenOnNullableExhaustivenessChecker.getMissingCases(expression, context, subjectDescriptor, nullable) } override fun isApplicable(subjectType: KotlinType): Boolean { @@ -232,7 +233,8 @@ private object WhenOnSealedExhaustivenessChecker : WhenOnClassExhaustivenessChec val memberClassDescriptors = LinkedHashSet() collectNestedSubclasses(subjectDescriptor!!, subjectDescriptor, memberClassDescriptors) // When on a sealed class without derived members is considered non-exhaustive (see test WhenOnEmptySealed) - return getMissingClassCases(expression, memberClassDescriptors, context) + return getMissingClassCases(expression, memberClassDescriptors, context) + + WhenOnNullableExhaustivenessChecker.getMissingCases(expression, context, subjectDescriptor, nullable) } override fun isApplicable(subjectType: KotlinType): Boolean { @@ -259,8 +261,7 @@ object WhenChecker { private val exhaustivenessCheckers = listOf(WhenOnBooleanExhaustivenessChecker, WhenOnEnumExhaustivenessChecker, - WhenOnSealedExhaustivenessChecker, - WhenOnNullableExhaustivenessChecker) + WhenOnSealedExhaustivenessChecker) @JvmStatic fun getNecessaryCases(expression: KtWhenExpression, context: BindingContext) = diff --git a/idea/testData/checker/WhenNonExhaustive.kt b/idea/testData/checker/WhenNonExhaustive.kt index ebb895904d4..db7c914a8f8 100644 --- a/idea/testData/checker/WhenNonExhaustive.kt +++ b/idea/testData/checker/WhenNonExhaustive.kt @@ -6,6 +6,11 @@ fun nonExhaustiveBoolean(b: Boolean) = when(b) { + false -> 0 + true -> 1 +} + enum class Color { RED, GREEN, @@ -48,6 +53,11 @@ fun nonExhaustiveSealed(v: Variant) = when(v) { + Variant.Singleton -> false + is Variant.Something -> true +} + sealed class Empty fun nonExhaustiveEmpty(e: Empty) = when(e) {}