One non-processed branch is now allowed for if statement #KT-10805 Fixed
Also #EA-64033 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
43b176de7e
commit
7e26fa6002
+41
-33
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user