FIR DFA: update receivers properly in case of single flow in merge point
This commit is contained in:
+6
@@ -14852,6 +14852,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt");
|
runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LookupTags.kt")
|
||||||
|
public void testLookupTags() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/fir/LookupTags.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("NameHighlighter.kt")
|
@TestMetadata("NameHighlighter.kt")
|
||||||
public void testNameHighlighter() throws Exception {
|
public void testNameHighlighter() throws Exception {
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ class PersistentImplicitReceiverStack private constructor(
|
|||||||
|
|
||||||
fun add(name: Name?, value: ImplicitReceiverValue<*>): PersistentImplicitReceiverStack {
|
fun add(name: Name?, value: ImplicitReceiverValue<*>): PersistentImplicitReceiverStack {
|
||||||
val stack = stack.add(value)
|
val stack = stack.add(value)
|
||||||
val originalTypes = originalTypes.add(value.type)
|
val originalTypes = originalTypes.add(value.originalType)
|
||||||
val index = stack.size - 1
|
val index = stack.size - 1
|
||||||
val indexesPerLabel = name?.let { indexesPerLabel.put(it, index) } ?: indexesPerLabel
|
val indexesPerLabel = name?.let { indexesPerLabel.put(it, index) } ?: indexesPerLabel
|
||||||
val indexesPerSymbol = indexesPerSymbol.put(value.boundSymbol, index)
|
val indexesPerSymbol = indexesPerSymbol.put(value.boundSymbol, index)
|
||||||
|
|||||||
+20
-7
@@ -582,7 +582,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
syntheticElseNode.mergeIncomingFlow()
|
syntheticElseNode.mergeIncomingFlow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
whenExitNode.mergeIncomingFlow(updateReceivers = true)
|
whenExitNode.mergeIncomingFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- While Loop -----------------------------------
|
// ----------------------------------- While Loop -----------------------------------
|
||||||
@@ -675,7 +675,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
fun enterFinallyBlock() {
|
fun enterFinallyBlock() {
|
||||||
// NB: fork to isolate effects inside the finally block
|
// NB: fork to isolate effects inside the finally block
|
||||||
// Otherwise, changes in the finally block could affect the previous nodes: try main block and catch clauses.
|
// Otherwise, changes in the finally block could affect the previous nodes: try main block and catch clauses.
|
||||||
graphBuilder.enterFinallyBlock().mergeIncomingFlow(shouldForkFlow = true)
|
graphBuilder.enterFinallyBlock().mergeIncomingFlow(updateReceivers = true, shouldForkFlow = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitFinallyBlock(tryExpression: FirTryExpression) {
|
fun exitFinallyBlock(tryExpression: FirTryExpression) {
|
||||||
@@ -1144,15 +1144,28 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
private val CFGNode<*>.origin: CFGNode<*> get() = if (this is StubNode) firstPreviousNode else this
|
private val CFGNode<*>.origin: CFGNode<*> get() = if (this is StubNode) firstPreviousNode else this
|
||||||
|
|
||||||
private fun <T : CFGNode<*>> T.mergeIncomingFlow(
|
private fun <T : CFGNode<*>> T.mergeIncomingFlow(
|
||||||
|
// This flag should be set true if we're changing flow branches from one to another (e.g. in when, try->catch)
|
||||||
updateReceivers: Boolean = false,
|
updateReceivers: Boolean = false,
|
||||||
shouldForkFlow: Boolean = false
|
shouldForkFlow: Boolean = false
|
||||||
): T = this.also { node ->
|
): T = this.also { node ->
|
||||||
val previousFlows = if (node.isDead)
|
val previousFlows = mutableListOf<FLOW>()
|
||||||
node.previousNodes.mapNotNull { runIf(!node.incomingEdges.getValue(it).kind.isBack) { it.flow } }
|
var deadForwardCount = 0
|
||||||
else
|
for (previousNode in previousNodes) {
|
||||||
node.previousNodes.mapNotNull { prev -> prev.takeIf { node.incomingEdges.getValue(it).kind.usedInDfa }?.flow }
|
val incomingEdgeKind = node.incomingEdges.getValue(previousNode).kind
|
||||||
|
if (node.isDead) {
|
||||||
|
if (!incomingEdgeKind.isBack) {
|
||||||
|
previousFlows += previousNode.flow
|
||||||
|
}
|
||||||
|
} else if (incomingEdgeKind.usedInDfa) {
|
||||||
|
previousFlows += previousNode.flow
|
||||||
|
}
|
||||||
|
if (incomingEdgeKind == EdgeKind.DeadForward) {
|
||||||
|
deadForwardCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
var flow = logicSystem.joinFlow(previousFlows)
|
var flow = logicSystem.joinFlow(previousFlows)
|
||||||
if (updateReceivers) {
|
// deadForwardCount should be added due to cases like merge after 'if (...) return else ...'
|
||||||
|
if (updateReceivers || previousFlows.size + deadForwardCount > 1) {
|
||||||
logicSystem.updateAllReceivers(flow)
|
logicSystem.updateAllReceivers(flow)
|
||||||
}
|
}
|
||||||
if (shouldForkFlow) {
|
if (shouldForkFlow) {
|
||||||
|
|||||||
@@ -138,9 +138,6 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
|
|||||||
}
|
}
|
||||||
|
|
||||||
commonFlow.addVariableAliases(aliasedVariablesThatDontChangeAlias)
|
commonFlow.addVariableAliases(aliasedVariablesThatDontChangeAlias)
|
||||||
|
|
||||||
updateAllReceivers(commonFlow)
|
|
||||||
|
|
||||||
return commonFlow
|
return commonFlow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
|
abstract class ConeClassLikeLookupTag {
|
||||||
|
abstract val status: String
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConeClassLikeLookupTagImpl : ConeClassLikeLookupTag() {
|
||||||
|
override var status: String = ""
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun change(newStatus: String) {
|
||||||
|
status = newStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConeClassLikeErrorLookupTag : ConeClassLikeLookupTag() {
|
||||||
|
override val status: String
|
||||||
|
get() = "ERROR"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ConeClassLikeLookupTag.foo(): String {
|
||||||
|
(this as? ConeClassLikeLookupTagImpl)?.status?.takeIf { it == "OK" }?.let { return it }
|
||||||
|
return status.also {
|
||||||
|
(this as? ConeClassLikeLookupTagImpl)?.bar(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ConeClassLikeLookupTagImpl.bar(s: String) {
|
||||||
|
change(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val tag = ConeClassLikeErrorLookupTag()
|
||||||
|
tag.foo()
|
||||||
|
val tag2 = ConeClassLikeLookupTagImpl()
|
||||||
|
tag2.change("OK")
|
||||||
|
tag2.foo()
|
||||||
|
return tag2.status
|
||||||
|
}
|
||||||
+6
@@ -14852,6 +14852,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt");
|
runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LookupTags.kt")
|
||||||
|
public void testLookupTags() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/fir/LookupTags.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("NameHighlighter.kt")
|
@TestMetadata("NameHighlighter.kt")
|
||||||
public void testNameHighlighter() throws Exception {
|
public void testNameHighlighter() throws Exception {
|
||||||
|
|||||||
+6
@@ -14852,6 +14852,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt");
|
runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LookupTags.kt")
|
||||||
|
public void testLookupTags() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/fir/LookupTags.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("NameHighlighter.kt")
|
@TestMetadata("NameHighlighter.kt")
|
||||||
public void testNameHighlighter() throws Exception {
|
public void testNameHighlighter() throws Exception {
|
||||||
|
|||||||
+5
@@ -12283,6 +12283,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt");
|
runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("LookupTags.kt")
|
||||||
|
public void testLookupTags() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/fir/LookupTags.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("NameHighlighter.kt")
|
@TestMetadata("NameHighlighter.kt")
|
||||||
public void testNameHighlighter() throws Exception {
|
public void testNameHighlighter() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/fir/NameHighlighter.kt");
|
runTest("compiler/testData/codegen/box/fir/NameHighlighter.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user