Fix KT-10775 Empty when causes compilation exception.

Expression type for an empty 'when' is 'kotlin.Unit'.
This commit is contained in:
Dmitry Petrov
2016-01-29 14:34:38 +03:00
parent dcc6262f47
commit b3f390abe5
3 changed files with 27 additions and 14 deletions
@@ -19,13 +19,11 @@ package org.jetbrains.kotlin.types.expressions
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean
import org.jetbrains.kotlin.cfg.WhenChecker
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
@@ -81,9 +79,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
checkSmartCastsInSubjectIfRequired(expression, contextBeforeSubject, subjectType)
val resolvedCall = resolveSpecialCallForWhen(expression, contextWithExpectedType, contextAfterSubject, subjectDataFlowValue, subjectType)
val whenReturnType = resolvedCall.resultingDescriptor.returnType
val dataFlowInfoForEntries = analyzeConditionsInWhenEntries(expression, contextAfterSubject, subjectDataFlowValue, subjectType)
val whenReturnType = inferTypeForWhenExpression(expression, contextWithExpectedType, contextAfterSubject, dataFlowInfoForEntries)
val whenResultValue = whenReturnType?.let { DataFlowValueFactory.createDataFlowValue(expression, it, contextAfterSubject) }
val (outputDataFlowInfo, jumpOutPossible) =
@@ -111,20 +108,21 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
return createTypeInfo(resultType, resultDataFlowInfo, jumpOutPossible, contextWithExpectedType.dataFlowInfo)
}
private fun resolveSpecialCallForWhen(
private fun inferTypeForWhenExpression(
expression: KtWhenExpression,
contextWithExpectedType: ExpressionTypingContext,
contextAfterSubject: ExpressionTypingContext,
subjectDataFlowValue: DataFlowValue,
subjectType: KotlinType
): ResolvedCall<FunctionDescriptor> {
dataFlowInfoForEntries: List<DataFlowInfo>
): KotlinType? {
if (expression.entries.all { it.expression == null }) {
return components.builtIns.unitType
}
val wrappedArgumentExpressions = wrapWhenEntryExpressionsAsSpecialCallArguments(expression)
val argumentDataFlowInfos = collectInputDataFlowForWhenEntryExpressions(expression, contextAfterSubject, subjectDataFlowValue, subjectType)
val callForWhen = createCallForSpecialConstruction(expression, expression, wrappedArgumentExpressions)
val dataFlowInfoForArguments = createDataFlowInfoForArgumentsOfWhenCall(callForWhen, contextAfterSubject.dataFlowInfo, argumentDataFlowInfos)
val dataFlowInfoForArguments = createDataFlowInfoForArgumentsOfWhenCall(callForWhen, contextAfterSubject.dataFlowInfo, dataFlowInfoForEntries)
return components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
val resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
callForWhen, ResolveConstruct.WHEN,
object : AbstractList<String>() {
override fun get(index: Int): String = "entry$index"
@@ -132,6 +130,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
},
Collections.nCopies(wrappedArgumentExpressions.size, false),
contextWithExpectedType, dataFlowInfoForArguments)
return resolvedCall.resultingDescriptor.returnType
}
private fun wrapWhenEntryExpressionsAsSpecialCallArguments(expression: KtWhenExpression): List<KtExpression> {
@@ -142,7 +142,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
return wrappedArgumentExpressions
}
private fun collectInputDataFlowForWhenEntryExpressions(
private fun analyzeConditionsInWhenEntries(
expression: KtWhenExpression,
contextAfterSubject: ExpressionTypingContext,
subjectDataFlowValue: DataFlowValue,
+7
View File
@@ -0,0 +1,7 @@
enum class A { X1, X2 }
fun box(): String {
when {}
when (A.X1) {}
return "OK"
}
@@ -8287,6 +8287,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("emptyWhen.kt")
public void testEmptyWhen() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/emptyWhen.kt");
doTest(fileName);
}
@TestMetadata("exhaustiveBoolean.kt")
public void testExhaustiveBoolean() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/exhaustiveBoolean.kt");