One non-processed branch is now allowed for if statement #KT-10805 Fixed

Also #EA-64033 Fixed
This commit is contained in:
Mikhail Glukhikh
2016-01-27 14:55:11 +03:00
committed by Mikhail Glukhikh
parent 43b176de7e
commit 7e26fa6002
4 changed files with 61 additions and 33 deletions
@@ -109,7 +109,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
if (elseBranch == null) {
if (thenBranch != null) {
KotlinTypeInfo result = getTypeInfoWhenOnlyOneBranchIsPresent(
thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression, isStatement);
thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression);
// If jump was possible, take condition check info as the jump info
return result.getJumpOutPossible()
? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo)
@@ -119,7 +119,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
}
if (thenBranch == null) {
return getTypeInfoWhenOnlyOneBranchIsPresent(
elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression, isStatement);
elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression);
}
KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression);
KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch);
@@ -135,42 +135,51 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
BindingContext bindingContext = context.trace.getBindingContext();
KotlinTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, bindingContext);
KotlinTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, bindingContext);
assert thenTypeInfo != null : "'Then' branch of if expression was not processed: " + ifExpression;
assert elseTypeInfo != null : "'Else' branch of if expression was not processed: " + ifExpression;
assert thenTypeInfo != null || elseTypeInfo != null : "Both branches of if expression were not processed: " + ifExpression.getText();
KotlinType resultType = resolvedCall.getResultingDescriptor().getReturnType();
KotlinType thenType = thenTypeInfo.getType();
KotlinType elseType = elseTypeInfo.getType();
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
if (resultType != null && thenType != null && elseType != null) {
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue);
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue);
}
boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition ||
thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition;
DataFlowInfo resultDataFlowInfo;
if (thenType == null && elseType == null) {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
if (elseTypeInfo == null) {
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible();
resultDataFlowInfo = thenTypeInfo.getDataFlowInfo();
}
else if (thenType == null || (jumpInThen && !jumpInElse)) {
resultDataFlowInfo = elseDataFlowInfo;
}
else if (elseType == null || (jumpInElse && !jumpInThen)) {
resultDataFlowInfo = thenDataFlowInfo;
else if (thenTypeInfo == null) {
loopBreakContinuePossible |= elseTypeInfo.getJumpOutPossible();
resultDataFlowInfo = elseTypeInfo.getDataFlowInfo();
}
else {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
}
KotlinType thenType = thenTypeInfo.getType();
KotlinType elseType = elseTypeInfo.getType();
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
if (resultType != null && thenType != null && elseType != null) {
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue);
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue);
}
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
if (thenType == null && elseType == null) {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
}
else if (thenType == null || (jumpInThen && !jumpInElse)) {
resultDataFlowInfo = elseDataFlowInfo;
}
else if (elseType == null || (jumpInElse && !jumpInThen)) {
resultDataFlowInfo = thenDataFlowInfo;
}
else {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
}
}
// If break or continue was possible, take condition check info as the jump info
return TypeInfoFactoryKt.createTypeInfo(resultType, resultDataFlowInfo, loopBreakContinuePossible,
loopBreakContinuePossibleInCondition ? context.dataFlowInfo : conditionDataFlowInfo);
@@ -183,8 +192,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
@NotNull DataFlowInfo presentInfo,
@NotNull DataFlowInfo otherInfo,
@NotNull ExpressionTypingContext context,
@NotNull KtIfExpression ifExpression,
boolean isStatement
@NotNull KtIfExpression ifExpression
) {
ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE)
.replaceContextDependency(INDEPENDENT);
@@ -0,0 +1,11 @@
// AssertionError for nested ifs with lambdas and Nothing as results
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>fn<!> = if (true) {
<!TYPE_MISMATCH!>{ true }<!>
}
else if (true) {
<!TYPE_MISMATCH!>{ true }<!>
}
else {
null!!
}
@@ -0,0 +1,3 @@
package
public val fn: kotlin.Nothing
@@ -2877,6 +2877,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("kt10805.kt")
public void testKt10805() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10805.kt");
doTest(fileName);
}
@TestMetadata("kt1156.kt")
public void testKt1156() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1156.kt");