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()) { if (operandVariable.isReal()) {
flow.addTypeStatement(operandVariable typeEq type) flow.addTypeStatement(operandVariable typeEq type)
} }
logicSystem.approveStatementsInsideFlow( if (!type.canBeNull) {
flow, logicSystem.approveStatementsInsideFlow(
operandVariable notEq null, flow,
shouldRemoveSynthetics = true, operandVariable notEq null,
shouldForkFlow = false shouldRemoveSynthetics = true,
) shouldForkFlow = false
)
} else {
val expressionVariable = variableStorage.createSyntheticVariable(typeOperatorCall)
flow.addImplication((expressionVariable notEq null) implies (operandVariable notEq null))
}
} }
FirOperation.SAFE_AS -> { FirOperation.SAFE_AS -> {
val expressionVariable = variableStorage.createSyntheticVariable(typeOperatorCall) val expressionVariable = variableStorage.createSyntheticVariable(typeOperatorCall)
flow.addImplication((expressionVariable notEq null) implies (operandVariable notEq null))
if (operandVariable.isReal()) { if (operandVariable.isReal()) {
flow.addImplication((expressionVariable notEq null) implies (operandVariable typeEq type)) flow.addImplication((expressionVariable notEq null) implies (operandVariable typeEq type))
flow.addImplication((expressionVariable eq null) implies (operandVariable typeNotEq type)) if (!type.canBeNull) {
} flow.addImplication((expressionVariable eq null) implies (operandVariable typeNotEq type))
if (type.nullability == ConeNullability.NOT_NULL) { }
flow.addImplication((expressionVariable notEq null) implies (operandVariable notEq null))
} }
} }
@@ -38,11 +38,11 @@ fun case_2(x: Class?) {
*/ */
fun case_3(x: Any?) { fun case_3(x: Any?) {
if ((x as Class?)?.prop_8?.prop_8?.prop_8?.prop_8 == null) else { 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<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class?")!>x<!><!UNSAFE_CALL!>.<!>prop_8 <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class")!>x<!>.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<!>.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<!>.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<!>.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
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8.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
<!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?) { fun case_13(x: Any?) {
if (x as Boolean? ?: x!!) { if (x as Boolean? ?: x!!) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Boolean?")!>x<!><!UNSAFE_CALL!>.<!>not() <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Boolean")!>x<!>.not()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean?")!>select(x)<!><!UNSAFE_CALL!>.<!>not() <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>select(x)<!>.not()
} }
} }
@@ -20,24 +20,24 @@ fun case_2(x: Any?) {
// TESTCASE NUMBER: 3 // TESTCASE NUMBER: 3
fun case_3(x: Any?) { fun case_3(x: Any?) {
if (x as Number? is Int) { if (x as Number? is Int) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Number?")!>x<!> <!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<!>.<!UNRESOLVED_REFERENCE!>inv<!>()
} }
} }
// TESTCASE NUMBER: 4 // TESTCASE NUMBER: 4
fun case_4(x: Any?) { fun case_4(x: Any?) {
if (x as Class? is Class) { if (x as Class? is Class) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & Class?")!>x<!> <!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<!><!UNSAFE_CALL{LT}!>.<!>prop_1
} }
} }
// TESTCASE NUMBER: 5 // TESTCASE NUMBER: 5
fun case_5(x: Any?) { fun case_5(x: Any?) {
if (x as Nothing? is Nothing) { if (x as Nothing? is Nothing) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing?")!>x<!> <!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<!><!UNSAFE_CALL{LT}!>.<!><!UNRESOLVED_REFERENCE{LT}!>inv<!>()
} }
} }
@@ -51,8 +51,8 @@ fun case_6(x: Any?) {
// TESTCASE NUMBER: 7 // TESTCASE NUMBER: 7
fun case_7(x: Any?) { fun case_7(x: Any?) {
if (x as String? != null) { if (x as String? != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.String?")!>x<!> <!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<!><!UNSAFE_CALL{LT}!>.<!>length
} }
} }
@@ -19,8 +19,8 @@ fun case_2(x: Any?) {
// TESTCASE NUMBER: 3 // TESTCASE NUMBER: 3
fun case_3(x: Any?) { fun case_3(x: Any?) {
if (x as ClassLevel1? is ClassLevel1) { if (x as ClassLevel1? is ClassLevel1) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & ClassLevel1?")!>x<!> <!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<!>.test1()
} }
} }