[FIR] Fix various corner cases in DFA
This commit is contained in:
+27
-24
@@ -184,7 +184,9 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
flow.addTypeStatement(operandVariable typeEq any)
|
flow.addTypeStatement(operandVariable typeEq any)
|
||||||
}
|
}
|
||||||
if (isNotNullCheck) {
|
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 {
|
} else {
|
||||||
if (isNotNullCheck) {
|
if (isNotNullCheck) {
|
||||||
@@ -196,14 +198,13 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
FirOperation.AS -> {
|
FirOperation.AS -> {
|
||||||
if (operandVariable.isReal()) {
|
if (operandVariable.isReal()) {
|
||||||
flow.addTypeStatement(operandVariable typeEq type)
|
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 -> {
|
FirOperation.SAFE_AS -> {
|
||||||
@@ -329,6 +330,12 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
val argument = checkNotNullCall.argument
|
val argument = checkNotNullCall.argument
|
||||||
val operandVariable = variableStorage.getOrCreateRealVariable(argument.symbol, argument) ?: return
|
val operandVariable = variableStorage.getOrCreateRealVariable(argument.symbol, argument) ?: return
|
||||||
node.flow.addTypeStatement(operandVariable typeEq any)
|
node.flow.addTypeStatement(operandVariable typeEq any)
|
||||||
|
logicSystem.approveStatementsInsideFlow(
|
||||||
|
node.flow,
|
||||||
|
operandVariable notEq null,
|
||||||
|
shouldRemoveSynthetics = true,
|
||||||
|
shouldForkFlow = false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- When -----------------------------------
|
// ----------------------------------- When -----------------------------------
|
||||||
@@ -511,22 +518,19 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
?.withNullability(ConeNullability.NOT_NULL)
|
?.withNullability(ConeNullability.NOT_NULL)
|
||||||
?: return@let
|
?: return@let
|
||||||
|
|
||||||
when (val variable = variableStorage.getOrCreateVariable(receiver)) {
|
val variable = variableStorage.getOrCreateVariable(receiver)
|
||||||
is RealVariable -> {
|
if (variable is RealVariable) {
|
||||||
if (shouldFork) {
|
if (shouldFork) {
|
||||||
flow = logicSystem.forkFlow(flow)
|
flow = logicSystem.forkFlow(flow)
|
||||||
}
|
|
||||||
flow.addTypeStatement(variable typeEq type)
|
|
||||||
}
|
|
||||||
is SyntheticVariable -> {
|
|
||||||
flow = logicSystem.approveStatementsInsideFlow(
|
|
||||||
flow,
|
|
||||||
variable notEq null,
|
|
||||||
shouldFork,
|
|
||||||
shouldRemoveSynthetics = true
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
flow.addTypeStatement(variable typeEq type)
|
||||||
}
|
}
|
||||||
|
flow = logicSystem.approveStatementsInsideFlow(
|
||||||
|
flow,
|
||||||
|
variable notEq null,
|
||||||
|
shouldFork,
|
||||||
|
shouldRemoveSynthetics = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
node.flow = flow
|
node.flow = flow
|
||||||
@@ -654,9 +658,8 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
variableStorage.getOrCreateRealVariable(initializer.symbol, initializer)?.let { initializerVariable ->
|
variableStorage.getOrCreateRealVariable(initializer.symbol, initializer)?.let { initializerVariable ->
|
||||||
if (initializerVariable.isStable) {
|
if (initializerVariable.isStable) {
|
||||||
variableStorage.attachSymbolToVariable(variable.symbol, initializerVariable)
|
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) {
|
if (!isVariableDeclaration) {
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ fun kt4565_1(a: SomeClass?) {
|
|||||||
a.data.hashCode()
|
a.data.hashCode()
|
||||||
}
|
}
|
||||||
if (a?.data is String) {
|
if (a?.data is String) {
|
||||||
a.<!INAPPLICABLE_CANDIDATE!>data<!>.<!UNRESOLVED_REFERENCE!>length<!>
|
a.data.length
|
||||||
data.length
|
data.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -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
|
$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>
|
<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
|
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
|
element: CONST Int type=kotlin.Int value=6
|
||||||
FUN name:testExtensionReceiver visibility:public modality:FINAL <> ($receiver:kotlin.collections.MutableList<kotlin.Any>) returnType:kotlin.Unit
|
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>
|
$receiver: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableList<kotlin.Any>
|
||||||
|
|||||||
Reference in New Issue
Block a user