[FIR] Fix various corner cases in DFA

This commit is contained in:
Mikhail Glukhikh
2020-02-05 20:27:23 +03:00
parent 1344d6407c
commit a8e89a6390
3 changed files with 30 additions and 26 deletions
@@ -184,7 +184,9 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
flow.addTypeStatement(operandVariable typeEq any)
}
if (isNotNullCheck) {
flow.addImplication((expressionVariable eq true) implies (operandVariable typeEq any)) }
flow.addImplication((expressionVariable eq true) implies (operandVariable typeEq any))
flow.addImplication((expressionVariable eq true) implies (operandVariable notEq null))
}
} else {
if (isNotNullCheck) {
@@ -196,14 +198,13 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
FirOperation.AS -> {
if (operandVariable.isReal()) {
flow.addTypeStatement(operandVariable typeEq type)
} else {
logicSystem.approveStatementsInsideFlow(
flow,
operandVariable notEq null,
shouldRemoveSynthetics = true,
shouldForkFlow = false
)
}
logicSystem.approveStatementsInsideFlow(
flow,
operandVariable notEq null,
shouldRemoveSynthetics = true,
shouldForkFlow = false
)
}
FirOperation.SAFE_AS -> {
@@ -329,6 +330,12 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
val argument = checkNotNullCall.argument
val operandVariable = variableStorage.getOrCreateRealVariable(argument.symbol, argument) ?: return
node.flow.addTypeStatement(operandVariable typeEq any)
logicSystem.approveStatementsInsideFlow(
node.flow,
operandVariable notEq null,
shouldRemoveSynthetics = true,
shouldForkFlow = false
)
}
// ----------------------------------- When -----------------------------------
@@ -511,22 +518,19 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
?.withNullability(ConeNullability.NOT_NULL)
?: return@let
when (val variable = variableStorage.getOrCreateVariable(receiver)) {
is RealVariable -> {
if (shouldFork) {
flow = logicSystem.forkFlow(flow)
}
flow.addTypeStatement(variable typeEq type)
}
is SyntheticVariable -> {
flow = logicSystem.approveStatementsInsideFlow(
flow,
variable notEq null,
shouldFork,
shouldRemoveSynthetics = true
)
val variable = variableStorage.getOrCreateVariable(receiver)
if (variable is RealVariable) {
if (shouldFork) {
flow = logicSystem.forkFlow(flow)
}
flow.addTypeStatement(variable typeEq type)
}
flow = logicSystem.approveStatementsInsideFlow(
flow,
variable notEq null,
shouldFork,
shouldRemoveSynthetics = true
)
}
node.flow = flow
@@ -654,9 +658,8 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
variableStorage.getOrCreateRealVariable(initializer.symbol, initializer)?.let { initializerVariable ->
if (initializerVariable.isStable) {
variableStorage.attachSymbolToVariable(variable.symbol, initializerVariable)
} else {
node.flow.addImplication((propertyVariable notEq null) implies (initializerVariable notEq null))
}
node.flow.addImplication((propertyVariable notEq null) implies (initializerVariable notEq null))
}
if (!isVariableDeclaration) {
@@ -52,7 +52,7 @@ fun kt4565_1(a: SomeClass?) {
a.data.hashCode()
}
if (a?.data is String) {
a.<!INAPPLICABLE_CANDIDATE!>data<!>.<!UNRESOLVED_REFERENCE!>length<!>
a.data.length
data.length
}
}
+2 -1
View File
@@ -58,7 +58,8 @@ FILE fqName:<root> fileName:/kt30020.kt
$receiver: CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.collections.MutableList<kotlin.Any> origin=EXCLEXCL
<T0>: kotlin.collections.MutableList<kotlin.Any>
arg0: CALL 'public abstract fun f (): kotlin.collections.MutableList<kotlin.Any> declared in <root>.X' type=kotlin.collections.MutableList<kotlin.Any>? origin=null
$this: GET_VAR 'nx: <root>.X? declared in <root>.test' type=<root>.X? origin=null
$this: TYPE_OP type=<root>.X origin=IMPLICIT_CAST typeOperand=<root>.X
GET_VAR 'nx: <root>.X? declared in <root>.test' type=<root>.X? origin=null
element: CONST Int type=kotlin.Int value=6
FUN name:testExtensionReceiver visibility:public modality:FINAL <> ($receiver:kotlin.collections.MutableList<kotlin.Any>) returnType:kotlin.Unit
$receiver: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableList<kotlin.Any>