[FIR] Drop subgraphs of lambda arguments of delegate calls

This commit is contained in:
Dmitriy Novozhilov
2020-03-31 11:21:44 +03:00
parent 14db88cccb
commit 9fa0a2cc77
4 changed files with 53 additions and 0 deletions
@@ -122,6 +122,10 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
return graphBuilder.returnExpressionsOfAnonymousFunction(function)
}
fun dropSubgraphFromCall(call: FirFunctionCall) {
graphBuilder.dropSubgraphFromCall(call)
}
// ----------------------------------- Named function -----------------------------------
fun enterFunction(function: FirFunction<*>) {
@@ -42,6 +42,15 @@ class ControlFlowGraph(val declaration: FirDeclaration?, val name: String, val k
_subGraphs += graph
}
internal fun removeSubGraph(graph: ControlFlowGraph) {
assert(graph.owner == this)
_subGraphs.remove(graph)
graph.owner = null
CFGNode.removeAllIncomingEdges(graph.enterNode)
CFGNode.removeAllOutgoingEdges(graph.exitNode)
}
enum class Kind {
Function, ClassInitializer, TopLevel
}
@@ -67,6 +76,24 @@ sealed class CFGNode<out E : FirElement>(val owner: ControlFlowGraph, val level:
to.isDead = true
}
}
internal fun removeAllIncomingEdges(to: CFGNode<*>) {
for (from in to._previousNodes) {
from._followingNodes.remove(to)
from._outgoingEdges.remove(to)
to._incomingEdges.remove(from)
}
to._previousNodes.clear()
}
internal fun removeAllOutgoingEdges(from: CFGNode<*>) {
for (to in from._followingNodes) {
to._previousNodes.remove(from)
from._outgoingEdges.remove(to)
to._incomingEdges.remove(from)
}
from._followingNodes.clear()
}
}
init {
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.types.isNothing
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitorVoid
import kotlin.random.Random
class ControlFlowGraphBuilder {
@@ -921,4 +922,24 @@ class ControlFlowGraphBuilder {
exitsOfAnonymousFunctions.clear()
exitsFromCompletedPostponedAnonymousFunctions.clear()
}
fun dropSubgraphFromCall(call: FirFunctionCall) {
val graphs = mutableListOf<ControlFlowGraph>()
call.acceptChildren(object : FirDefaultVisitorVoid() {
override fun visitElement(element: FirElement) {
element.acceptChildren(this)
}
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
anonymousFunction.controlFlowGraphReference.controlFlowGraph?.let {
graphs += it
}
}
}, null)
val currentGraph = graph
for (graph in graphs) {
currentGraph.removeSubGraph(graph)
}
}
}
@@ -185,6 +185,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
}
}
(delegateProvider as? FirFunctionCall)?.let { dataFlowAnalyzer.dropSubgraphFromCall(it) }
return wrappedDelegateExpression.expression.transform(transformer, ResolutionMode.ContextDependent)
} finally {
dataFlowAnalyzer.exitDelegateExpression()