From a8e89a63900732990046cf9c32033226452ea551 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 5 Feb 2020 20:27:23 +0300 Subject: [PATCH] [FIR] Fix various corner cases in DFA --- .../fir/resolve/dfa/FirDataFlowAnalyzer.kt | 51 ++++++++++--------- .../safeAccessReceiverNotNull.fir.kt | 2 +- .../ir/irText/expressions/kt30020.fir.txt | 3 +- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index 9cdeda19508..89e741b9de2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt @@ -184,7 +184,9 @@ abstract class FirDataFlowAnalyzer( 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( 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( 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( ?.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( 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) { diff --git a/compiler/testData/diagnostics/tests/smartCasts/safecalls/safeAccessReceiverNotNull.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/safecalls/safeAccessReceiverNotNull.fir.kt index 5051bd8e845..4e93259c46b 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/safecalls/safeAccessReceiverNotNull.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/safecalls/safeAccessReceiverNotNull.fir.kt @@ -52,7 +52,7 @@ fun kt4565_1(a: SomeClass?) { a.data.hashCode() } if (a?.data is String) { - a.data.length + a.data.length data.length } } diff --git a/compiler/testData/ir/irText/expressions/kt30020.fir.txt b/compiler/testData/ir/irText/expressions/kt30020.fir.txt index 087e49dc391..ebcf3aa2ad7 100644 --- a/compiler/testData/ir/irText/expressions/kt30020.fir.txt +++ b/compiler/testData/ir/irText/expressions/kt30020.fir.txt @@ -58,7 +58,8 @@ FILE fqName: fileName:/kt30020.kt $receiver: CALL 'public final fun CHECK_NOT_NULL (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 origin=EXCLEXCL : kotlin.collections.MutableList arg0: CALL 'public abstract fun f (): kotlin.collections.MutableList declared in .X' type=kotlin.collections.MutableList? origin=null - $this: GET_VAR 'nx: .X? declared in .test' type=.X? origin=null + $this: TYPE_OP type=.X origin=IMPLICIT_CAST typeOperand=.X + GET_VAR 'nx: .X? declared in .test' type=.X? origin=null element: CONST Int type=kotlin.Int value=6 FUN name:testExtensionReceiver visibility:public modality:FINAL <> ($receiver:kotlin.collections.MutableList) returnType:kotlin.Unit $receiver: VALUE_PARAMETER name: type:kotlin.collections.MutableList