FIR DFA: generate more correct implications on as/as?

^KT-54851 Fixed
This commit is contained in:
pyos
2022-11-11 18:49:29 +01:00
committed by teamcity
parent 6a2d74e211
commit 623dfdd5a3
5 changed files with 33 additions and 28 deletions
@@ -446,22 +446,27 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
if (operandVariable.isReal()) {
flow.addTypeStatement(operandVariable typeEq type)
}
logicSystem.approveStatementsInsideFlow(
flow,
operandVariable notEq null,
shouldRemoveSynthetics = true,
shouldForkFlow = false
)
if (!type.canBeNull) {
logicSystem.approveStatementsInsideFlow(
flow,
operandVariable notEq null,
shouldRemoveSynthetics = true,
shouldForkFlow = false
)
} else {
val expressionVariable = variableStorage.createSyntheticVariable(typeOperatorCall)
flow.addImplication((expressionVariable notEq null) implies (operandVariable notEq null))
}
}
FirOperation.SAFE_AS -> {
val expressionVariable = variableStorage.createSyntheticVariable(typeOperatorCall)
flow.addImplication((expressionVariable notEq null) implies (operandVariable notEq null))
if (operandVariable.isReal()) {
flow.addImplication((expressionVariable notEq null) implies (operandVariable typeEq type))
flow.addImplication((expressionVariable eq null) implies (operandVariable typeNotEq type))
}
if (type.nullability == ConeNullability.NOT_NULL) {
flow.addImplication((expressionVariable notEq null) implies (operandVariable notEq null))
if (!type.canBeNull) {
flow.addImplication((expressionVariable eq null) implies (operandVariable typeNotEq type))
}
}
}
@@ -38,11 +38,11 @@ fun case_2(x: Class?) {
*/
fun case_3(x: Any?) {
if ((x as Class?)?.prop_8?.prop_8?.prop_8?.prop_8 == null) else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class?")!>x<!><!UNSAFE_CALL!>.<!>prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class?")!>x<!><!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class?")!>x<!><!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class?")!>x<!><!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class")!>x<!>.prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class")!>x<!>.prop_8<!UNSAFE_CALL!>.<!>prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class")!>x<!>.prop_8<!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class")!>x<!>.prop_8<!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8
}
}
@@ -87,7 +87,7 @@ fun case_6(x: Class?) {
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8.prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8.prop_8.prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8.prop_8.prop_8<!UNSAFE_CALL!>.<!>prop_8<!UNSAFE_CALL!>.<!>prop_8
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8.prop_8.prop_8.prop_8<!UNSAFE_CALL!>.<!>prop_8
}
}
@@ -120,8 +120,8 @@ fun case_12(x: Any?) {
*/
fun case_13(x: Any?) {
if (x as Boolean? ?: x!!) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Boolean?")!>x<!><!UNSAFE_CALL!>.<!>not()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean?")!>select(x)<!><!UNSAFE_CALL!>.<!>not()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Boolean")!>x<!>.not()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>select(x)<!>.not()
}
}
@@ -20,24 +20,24 @@ fun case_2(x: Any?) {
// TESTCASE NUMBER: 3
fun case_3(x: Any?) {
if (x as Number? is Int) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Number?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Number?")!>x<!>.<!UNRESOLVED_REFERENCE!>inv<!>()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Number")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Number")!>x<!>.<!UNRESOLVED_REFERENCE!>inv<!>()
}
}
// TESTCASE NUMBER: 4
fun case_4(x: Any?) {
if (x as Class? is Class) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class?")!>x<!><!UNSAFE_CALL!>.<!>prop_1
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class")!>x<!><!UNSAFE_CALL{LT}!>.<!>prop_1
}
}
// TESTCASE NUMBER: 5
fun case_5(x: Any?) {
if (x as Nothing? is Nothing) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing?")!>x<!><!UNSAFE_CALL!>.<!><!UNRESOLVED_REFERENCE{LT}!>inv<!>()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!><!UNSAFE_CALL{LT}!>.<!><!UNRESOLVED_REFERENCE{LT}!>inv<!>()
}
}
@@ -51,8 +51,8 @@ fun case_6(x: Any?) {
// TESTCASE NUMBER: 7
fun case_7(x: Any?) {
if (x as String? != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.String?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.String?")!>x<!><!UNSAFE_CALL!>.<!>length
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.String")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.String")!>x<!><!UNSAFE_CALL{LT}!>.<!>length
}
}
@@ -19,8 +19,8 @@ fun case_2(x: Any?) {
// TESTCASE NUMBER: 3
fun case_3(x: Any?) {
if (x as ClassLevel1? is ClassLevel1) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & ClassLevel1?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & ClassLevel1?")!>x<!><!UNSAFE_CALL!>.<!>test1()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & ClassLevel1")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & ClassLevel1")!>x<!>.test1()
}
}