Solution for KT-7838: now data flow information at the end of when expression is determined correctly.

#KT-7838  Fixed.
This commit is contained in:
Mikhail Glukhikh
2015-05-26 17:37:53 +03:00
parent 9e69b74a15
commit 4fb331ecd3
10 changed files with 142 additions and 0 deletions
@@ -130,6 +130,11 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
if (commonDataFlowInfo == null) {
commonDataFlowInfo = context.dataFlowInfo;
}
else if (expression.getElseExpression() == null && !WhenChecker.isWhenExhaustive(expression, context.trace)) {
// Without else expression in non-exhaustive when, we *must* take initial data flow info into account,
// because data flow can bypass all when branches in this case
commonDataFlowInfo = commonDataFlowInfo.or(context.dataFlowInfo);
}
return TypeInfoFactoryPackage.createTypeInfo(expressionTypes.isEmpty() ? null : DataFlowUtils.checkType(
DataFlowUtils.checkImplicitCast(
@@ -0,0 +1,11 @@
class A
fun test(a: Any): String {
val q: String? = null
when (a) {
is A -> q!!
}
// When is not exhaustive
return <!TYPE_MISMATCH!>q<!>
}
@@ -0,0 +1,10 @@
package
internal fun test(/*0*/ a: kotlin.Any): kotlin.String
internal final class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,11 @@
class A
fun test(a: Any) {
var q: String? = null
when (a) {
is A -> q = "1"
}
// When is not exhaustive
return <!TYPE_MISMATCH!>q<!>
}
@@ -0,0 +1,10 @@
package
internal fun test(/*0*/ a: kotlin.Any): kotlin.Unit
internal final class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,12 @@
enum class My { A, B }
fun test(a: My): String {
val q: String?
when (a) {
My.A -> q = "1"
My.B -> q = "2"
}
// When is exhaustive
return <!DEBUG_INFO_SMARTCAST!>q<!>
}
@@ -0,0 +1,37 @@
package
internal fun test(/*0*/ a: My): kotlin.String
internal final enum class My : kotlin.Enum<My> {
public enum entry A : My {
private constructor A()
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: My): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public enum entry B : My {
private constructor B()
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: My): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
private constructor My()
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: My): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): My
public final /*synthesized*/ fun values(): kotlin.Array<My>
}
@@ -0,0 +1,12 @@
class A
fun test(a: Any): String {
var q: String?
when (a) {
is A -> q = "1"
else -> q = "2"
}
// When is not exhaustive
return <!DEBUG_INFO_SMARTCAST!>q<!>
}
@@ -0,0 +1,10 @@
package
internal fun test(/*0*/ a: kotlin.Any): kotlin.String
internal final class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -13548,6 +13548,30 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("BranchBypassVal.kt")
public void testBranchBypassVal() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/BranchBypassVal.kt");
doTest(fileName);
}
@TestMetadata("BranchBypassVar.kt")
public void testBranchBypassVar() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/BranchBypassVar.kt");
doTest(fileName);
}
@TestMetadata("BranchFalseBypass.kt")
public void testBranchFalseBypass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/BranchFalseBypass.kt");
doTest(fileName);
}
@TestMetadata("BranchFalseBypassElse.kt")
public void testBranchFalseBypassElse() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/BranchFalseBypassElse.kt");
doTest(fileName);
}
@TestMetadata("ElseOnNullableEnum.kt")
public void testElseOnNullableEnum() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.kt");