Skip to content

Commit 7e26fa6

Browse files
committed
One non-processed branch is now allowed for if statement #KT-10805 Fixed
Also #EA-64033 Fixed
1 parent 43b176d commit 7e26fa6

File tree

4 files changed

+61
-33
lines changed

4 files changed

+61
-33
lines changed

compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public KotlinTypeInfo visitIfExpression(KtIfExpression ifExpression, ExpressionT
109109
if (elseBranch == null) {
110110
if (thenBranch != null) {
111111
KotlinTypeInfo result = getTypeInfoWhenOnlyOneBranchIsPresent(
112-
thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression, isStatement);
112+
thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression);
113113
// If jump was possible, take condition check info as the jump info
114114
return result.getJumpOutPossible()
115115
? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo)
@@ -119,7 +119,7 @@ public KotlinTypeInfo visitIfExpression(KtIfExpression ifExpression, ExpressionT
119119
}
120120
if (thenBranch == null) {
121121
return getTypeInfoWhenOnlyOneBranchIsPresent(
122-
elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression, isStatement);
122+
elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression);
123123
}
124124
KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression);
125125
KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch);
@@ -135,42 +135,51 @@ public KotlinTypeInfo visitIfExpression(KtIfExpression ifExpression, ExpressionT
135135
BindingContext bindingContext = context.trace.getBindingContext();
136136
KotlinTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, bindingContext);
137137
KotlinTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, bindingContext);
138-
assert thenTypeInfo != null : "'Then' branch of if expression was not processed: " + ifExpression;
139-
assert elseTypeInfo != null : "'Else' branch of if expression was not processed: " + ifExpression;
138+
assert thenTypeInfo != null || elseTypeInfo != null : "Both branches of if expression were not processed: " + ifExpression.getText();
140139

141140
KotlinType resultType = resolvedCall.getResultingDescriptor().getReturnType();
142-
KotlinType thenType = thenTypeInfo.getType();
143-
KotlinType elseType = elseTypeInfo.getType();
144-
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
145-
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
146-
if (resultType != null && thenType != null && elseType != null) {
147-
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
148-
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
149-
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue);
150-
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
151-
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue);
152-
}
153-
154-
boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition ||
155-
thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
156-
157-
boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
158-
boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
159-
141+
boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition;
160142
DataFlowInfo resultDataFlowInfo;
161-
if (thenType == null && elseType == null) {
162-
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
163-
}
164-
else if (thenType == null || (jumpInThen && !jumpInElse)) {
165-
resultDataFlowInfo = elseDataFlowInfo;
143+
144+
if (elseTypeInfo == null) {
145+
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible();
146+
resultDataFlowInfo = thenTypeInfo.getDataFlowInfo();
166147
}
167-
else if (elseType == null || (jumpInElse && !jumpInThen)) {
168-
resultDataFlowInfo = thenDataFlowInfo;
148+
else if (thenTypeInfo == null) {
149+
loopBreakContinuePossible |= elseTypeInfo.getJumpOutPossible();
150+
resultDataFlowInfo = elseTypeInfo.getDataFlowInfo();
169151
}
170152
else {
171-
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
172-
}
153+
KotlinType thenType = thenTypeInfo.getType();
154+
KotlinType elseType = elseTypeInfo.getType();
155+
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
156+
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
157+
if (resultType != null && thenType != null && elseType != null) {
158+
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
159+
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
160+
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue);
161+
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
162+
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue);
163+
}
173164

165+
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
166+
167+
boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
168+
boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
169+
170+
if (thenType == null && elseType == null) {
171+
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
172+
}
173+
else if (thenType == null || (jumpInThen && !jumpInElse)) {
174+
resultDataFlowInfo = elseDataFlowInfo;
175+
}
176+
else if (elseType == null || (jumpInElse && !jumpInThen)) {
177+
resultDataFlowInfo = thenDataFlowInfo;
178+
}
179+
else {
180+
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
181+
}
182+
}
174183
// If break or continue was possible, take condition check info as the jump info
175184
return TypeInfoFactoryKt.createTypeInfo(resultType, resultDataFlowInfo, loopBreakContinuePossible,
176185
loopBreakContinuePossibleInCondition ? context.dataFlowInfo : conditionDataFlowInfo);
@@ -183,8 +192,7 @@ private KotlinTypeInfo getTypeInfoWhenOnlyOneBranchIsPresent(
183192
@NotNull DataFlowInfo presentInfo,
184193
@NotNull DataFlowInfo otherInfo,
185194
@NotNull ExpressionTypingContext context,
186-
@NotNull KtIfExpression ifExpression,
187-
boolean isStatement
195+
@NotNull KtIfExpression ifExpression
188196
) {
189197
ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE)
190198
.replaceContextDependency(INDEPENDENT);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// AssertionError for nested ifs with lambdas and Nothing as results
2+
3+
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>fn<!> = if (true) {
4+
<!TYPE_MISMATCH!>{ true }<!>
5+
}
6+
else if (true) {
7+
<!TYPE_MISMATCH!>{ true }<!>
8+
}
9+
else {
10+
null!!
11+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package
2+
3+
public val fn: kotlin.Nothing

compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2877,6 +2877,12 @@ public void testKt1066() throws Exception {
28772877
doTest(fileName);
28782878
}
28792879

2880+
@TestMetadata("kt10805.kt")
2881+
public void testKt10805() throws Exception {
2882+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10805.kt");
2883+
doTest(fileName);
2884+
}
2885+
28802886
@TestMetadata("kt1156.kt")
28812887
public void testKt1156() throws Exception {
28822888
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1156.kt");

0 commit comments

Comments
 (0)