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 6d363afe64e..07a41aa9bad 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 @@ -122,9 +122,7 @@ abstract class FirDataFlowAnalyzer( fun exitFunction(function: FirFunction<*>): ControlFlowGraph? { val (node, graph) = graphBuilder.exitFunction(function) - if (function.body == null) { - node.mergeIncomingFlow() - } + node.mergeIncomingFlow() if (!graphBuilder.isTopLevel()) { for (valueParameter in function.valueParameters) { variableStorage.removeRealVariable(valueParameter.symbol) @@ -144,6 +142,7 @@ abstract class FirDataFlowAnalyzer( val (enterNode, exitNode) = graphBuilder.visitPostponedAnonymousFunction(anonymousFunction) enterNode.mergeIncomingFlow() exitNode.mergeIncomingFlow() + enterNode.flow = enterNode.flow.fork() } // ----------------------------------- Anonymous object ----------------------------------- @@ -352,18 +351,21 @@ abstract class FirDataFlowAnalyzer( // ----------------------------------- Check not null call ----------------------------------- - fun exitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall) { + fun exitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, callCompleted: Boolean) { // Add `Any` to the set of possible types; the intersection type `T? & Any` will be reduced to `T` after smartcast. - val node = graphBuilder.exitCheckNotNullCall(checkNotNullCall).mergeIncomingFlow() + val (node, unionNode) = graphBuilder.exitCheckNotNullCall(checkNotNullCall, callCompleted) + node.mergeIncomingFlow() val argument = checkNotNullCall.argument - val operandVariable = variableStorage.getOrCreateRealVariable(node.previousFlow, argument.symbol, argument) ?: return - node.flow.addTypeStatement(operandVariable typeEq any) - logicSystem.approveStatementsInsideFlow( - node.flow, - operandVariable notEq null, - shouldRemoveSynthetics = true, - shouldForkFlow = false - ) + variableStorage.getOrCreateRealVariable(node.previousFlow, argument.symbol, argument)?.let { operandVariable -> + node.flow.addTypeStatement(operandVariable typeEq any) + logicSystem.approveStatementsInsideFlow( + node.flow, + operandVariable notEq null, + shouldRemoveSynthetics = true, + shouldForkFlow = false + ) + } + unionNode?.let { unionFlowFromArguments(it) } } // ----------------------------------- When ----------------------------------- @@ -405,8 +407,8 @@ abstract class FirDataFlowAnalyzer( graphBuilder.exitWhenBranchResult(whenBranch).mergeIncomingFlow() } - fun exitWhenExpression(whenExpression: FirWhenExpression) { - val (whenExitNode, syntheticElseNode) = graphBuilder.exitWhenExpression(whenExpression) + fun exitWhenExpression(whenExpression: FirWhenExpression, callCompleted: Boolean) { + val (whenExitNode, syntheticElseNode, unionNode) = graphBuilder.exitWhenExpression(whenExpression, callCompleted) if (syntheticElseNode != null) { val previousConditionExitNode = syntheticElseNode.firstPreviousNode as? WhenBranchConditionExitNode // previous node for syntheticElseNode can be not WhenBranchConditionExitNode in case of `when` without any branches @@ -424,6 +426,7 @@ abstract class FirDataFlowAnalyzer( } } whenExitNode.mergeIncomingFlow(updateReceivers = true) + unionNode?.let { unionFlowFromArguments(unionNode) } } // ----------------------------------- While Loop ----------------------------------- @@ -519,9 +522,11 @@ abstract class FirDataFlowAnalyzer( graphBuilder.exitFinallyBlock(tryExpression).mergeIncomingFlow() } - fun exitTryExpression(tryExpression: FirTryExpression) { + fun exitTryExpression(tryExpression: FirTryExpression, callCompleted: Boolean) { // TODO - graphBuilder.exitTryExpression(tryExpression).mergeIncomingFlow() + val (tryExpressionExitNode, unionNode) = graphBuilder.exitTryExpression(tryExpression, callCompleted) + tryExpressionExitNode.mergeIncomingFlow() + unionNode?.let { unionFlowFromArguments(it) } } // ----------------------------------- Resolvable call ----------------------------------- @@ -571,10 +576,16 @@ abstract class FirDataFlowAnalyzer( exitSafeCall(qualifiedAccessExpression) } - fun exitFunctionCall(functionCall: FirFunctionCall) { - val node = graphBuilder.exitFunctionCall(functionCall).mergeIncomingFlow() + fun enterFunctionCall(functionCall: FirFunctionCall) { + graphBuilder.enterFunctionCall(functionCall) + } + + fun exitFunctionCall(functionCall: FirFunctionCall, callCompleted: Boolean) { + val (functionCallNode, unionNode) = graphBuilder.exitFunctionCall(functionCall, callCompleted) + unionNode?.let { unionFlowFromArguments(it) } + functionCallNode.mergeIncomingFlow() if (functionCall.isBooleanNot()) { - exitBooleanNot(functionCall, node) + exitBooleanNot(functionCall, functionCallNode) } processConditionalContract(functionCall) if (functionCall.safe) { @@ -582,6 +593,12 @@ abstract class FirDataFlowAnalyzer( } } + private fun unionFlowFromArguments(node: UnionFunctionCallArgumentsNode) { + node.flow = logicSystem.unionFlow(node.previousNodes.map { it.flow }).also { + logicSystem.updateAllReceivers(it) + } + } + private fun exitSafeCall(qualifiedAccess: FirQualifiedAccess) { if (!qualifiedAccess.safe) return val node = graphBuilder.exitSafeCall(qualifiedAccess).mergeIncomingFlow() @@ -899,6 +916,10 @@ abstract class FirDataFlowAnalyzer( logicSystem.removeAllAboutVariable(this, variable) } + private fun FLOW.fork(): FLOW { + return logicSystem.forkFlow(this) + } + private val CFGNode<*>.previousFlow : FLOW get() = firstPreviousNode.flow } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/LogicSystem.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/LogicSystem.kt index e9b8194bdea..e0895021380 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/LogicSystem.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/LogicSystem.kt @@ -29,6 +29,7 @@ abstract class LogicSystem(protected val context: ConeInferenceCont abstract fun createEmptyFlow(): FLOW abstract fun forkFlow(flow: FLOW): FLOW abstract fun joinFlow(flows: Collection): FLOW + abstract fun unionFlow(flows: Collection): FLOW abstract fun addTypeStatement(flow: FLOW, statement: TypeStatement) @@ -142,6 +143,20 @@ abstract class LogicSystem(protected val context: ConeInferenceCont } return commonTypes } + + protected fun and(statements: Collection): MutableTypeStatement { + require(statements.isNotEmpty()) + statements.singleOrNull()?.let { return it as MutableTypeStatement } + val variable = statements.first().variable + assert(statements.all { it.variable == variable }) + val exactType = andForTypes(statements.map { it.exactType }) + val exactNotType = andForTypes(statements.map { it.exactNotType }) + return MutableTypeStatement(variable, exactType, exactNotType) + } + + private fun andForTypes(types: Collection>): MutableSet { + return types.flatMapTo(mutableSetOf()) { it } + } } fun LogicSystem.approveOperationStatement( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt index c83c5050f54..d5640c3eef9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt @@ -145,6 +145,43 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste return commonFlow } + override fun unionFlow(flows: Collection): PersistentFlow { + if (flows.isEmpty()) return createEmptyFlow() + flows.singleOrNull()?.let { return it } + + val flowsSize = flows.size + val aliasedVariablesThatDontChangeAlias = mutableMapOf() + flows.flatMapTo(mutableSetOf()) { it.directAliasMap.keys }.forEach { aliasedVariable -> + val originals = flows.map { it.directAliasMap[aliasedVariable] ?: return@forEach } + if (originals.size != flowsSize) return@forEach + val firstOriginal = originals.first() + if (originals.all { it == firstOriginal }) { + aliasedVariablesThatDontChangeAlias[aliasedVariable] = firstOriginal + } + } + + val commonFlow = flows.reduce(::lowestCommonFlow) + val allVariables = flows.flatMapTo(mutableSetOf()) { + it.diffVariablesIterable(commonFlow, aliasedVariablesThatDontChangeAlias.keys) + } + + for (variable in allVariables) { + val info = and(flows.map { it.getApprovedTypeStatementsDiff(variable, commonFlow) }) + commonFlow.approvedTypeStatements = commonFlow.approvedTypeStatements.addTypeStatement(info) + if (commonFlow.previousFlow != null) { + commonFlow.approvedTypeStatementsDiff = commonFlow.approvedTypeStatementsDiff.addTypeStatement(info) + } + } + + for ((alias, underlyingVariable) in aliasedVariablesThatDontChangeAlias) { + addLocalVariableAlias(commonFlow,alias, underlyingVariable) + } + + updateAllReceivers(commonFlow) + + return commonFlow + } + override fun addLocalVariableAlias(flow: PersistentFlow, alias: RealVariable, underlyingVariable: RealVariable) { removeLocalVariableAlias(flow, alias) flow.directAliasMap = flow.directAliasMap.put(alias, underlyingVariable) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt index 0f1e5c9f77d..efa3e3dcc9a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt @@ -91,6 +91,7 @@ sealed class CFGNode(val owner: ControlFlowGraph, val level: } val CFGNode<*>.firstPreviousNode: CFGNode<*> get() = previousNodes[0] +val CFGNode<*>.lastPreviousNode: CFGNode<*> get() = previousNodes.last() interface EnterNodeMarker interface ExitNodeMarker @@ -104,8 +105,9 @@ class FunctionExitNode(owner: ControlFlowGraph, override val fir: FirFunction<*> class PostponedLambdaEnterNode(owner: ControlFlowGraph, override val fir: FirAnonymousFunction, level: Int, id: Int) : CFGNode(owner, level, id) class PostponedLambdaExitNode(owner: ControlFlowGraph, override val fir: FirAnonymousFunction, level: Int, id: Int) : CFGNode(owner, level, id) +class UnionFunctionCallArgumentsNode(owner: ControlFlowGraph, override val fir: FirElement, level: Int, id: Int) : CFGNode(owner, level, id) -// ----------------------------------- Anonymous function ----------------------------------- +// ----------------------------------- Anonymous object ----------------------------------- class AnonymousObjectExitNode(owner: ControlFlowGraph, override val fir: FirAnonymousObject, level: Int, id: Int) : CFGNode(owner, level, id) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index 2ff1f69096c..02eac1daea4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -52,6 +52,8 @@ class ControlFlowGraphBuilder { private val entersToPostponedAnonymousFunctions: MutableMap, PostponedLambdaEnterNode> = mutableMapOf() private val exitsFromPostponedAnonymousFunctions: MutableMap, PostponedLambdaExitNode> = mutableMapOf() + private val exitsFromCompletedPostponedAnonymousFunctions: MutableList = mutableListOf() + var levelCounter: Int = 0 private set @@ -140,6 +142,9 @@ class ControlFlowGraphBuilder { } if (postponedExitNode != null) { CFGNode.addEdge(lastNodes.pop(), postponedExitNode, propagateDeadness = true, kind = EdgeKind.Cfg) + if (invocationKind == InvocationKind.EXACTLY_ONCE) { + exitsFromCompletedPostponedAnonymousFunctions += postponedExitNode + } } } else { if (function.body == null) { @@ -154,7 +159,9 @@ class ControlFlowGraphBuilder { } exitNode.updateDeadStatus() val graph = if (!isInplace) { - graphs.pop() + graphs.pop().also { graph -> + exitsFromCompletedPostponedAnonymousFunctions.removeAll { it.owner == graph } + } } else { null } @@ -285,8 +292,10 @@ class ControlFlowGraphBuilder { // ----------------------------------- Check not null call ----------------------------------- - fun exitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall): CheckNotNullCallNode { - return createCheckNotNullCallNode(checkNotNullCall).also { addNewSimpleNode(it) } + fun exitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, callCompleted: Boolean): Pair { + val node = createCheckNotNullCallNode(checkNotNullCall).also { addNewSimpleNode(it) } + val unionNode = processUnionOfArguments(node, callCompleted).second + return node to unionNode } // ----------------------------------- When ----------------------------------- @@ -324,7 +333,7 @@ class ControlFlowGraphBuilder { return node } - fun exitWhenExpression(whenExpression: FirWhenExpression): Pair { + fun exitWhenExpression(whenExpression: FirWhenExpression, callCompleted: Boolean): Triple { val whenExitNode = whenExitNodes.pop() // exit from last condition node still on stack // we should remove it @@ -337,8 +346,9 @@ class ControlFlowGraphBuilder { } else null whenExitNode.updateDeadStatus() lastNodes.push(whenExitNode) + val (_, unionNode) = processUnionOfArguments(whenExitNode, callCompleted) levelCounter-- - return whenExitNode to syntheticElseBranchNode + return Triple(whenExitNode, syntheticElseBranchNode, unionNode) } // ----------------------------------- While Loop ----------------------------------- @@ -577,13 +587,14 @@ class ControlFlowGraphBuilder { } } - fun exitTryExpression(tryExpression: FirTryExpression): TryExpressionExitNode { + fun exitTryExpression(tryExpression: FirTryExpression, callCompleted: Boolean): Pair { levelCounter-- catchNodeStorages.pop() val node = tryExitNodes.pop() node.updateDeadStatus() lastNodes.push(node) - return node + val (_, unionNode) = processUnionOfArguments(node, callCompleted) + return node to unionNode } // ----------------------------------- Resolvable call ----------------------------------- @@ -599,15 +610,58 @@ class ControlFlowGraphBuilder { return node } - fun exitFunctionCall(functionCall: FirFunctionCall): FunctionCallNode { + fun enterFunctionCall(functionCall: FirFunctionCall) { + levelCounter++ + } + + fun exitFunctionCall(functionCall: FirFunctionCall, callCompleted: Boolean): Pair { + levelCounter-- val returnsNothing = functionCall.resultType.isNothing val node = createFunctionCallNode(functionCall) + val (kind, unionNode) = processUnionOfArguments(node, callCompleted) if (returnsNothing) { - addNodeThatReturnsNothing(node) + addNodeThatReturnsNothing(node, preferredKind = kind) } else { - addNewSimpleNode(node) + addNewSimpleNode(node, preferredKind = kind) } - return node + return node to unionNode + } + + private fun processUnionOfArguments( + node: CFGNode<*>, + callCompleted: Boolean + ): Pair { + var kind = EdgeKind.Simple + if (!callCompleted || exitsFromCompletedPostponedAnonymousFunctions.isEmpty()) { + return EdgeKind.Simple to null + } + val unionNode by lazy { createUnionFunctionCallArgumentsNode(node.fir) } + var hasDirectPreviousNode = false + var hasPostponedLambdas = false + + val iterator = exitsFromCompletedPostponedAnonymousFunctions.iterator() + while (iterator.hasNext()) { + val exitNode = iterator.next() + if (node.level >= exitNode.level) continue + hasPostponedLambdas = true + if (exitNode == lastNode) { + addEdge(lastNodes.pop(), node, preferredKind = EdgeKind.Cfg) + kind = EdgeKind.Dfg + hasDirectPreviousNode = true + } + addEdge(exitNode.lastPreviousNode, unionNode, preferredKind = EdgeKind.Dfg) + iterator.remove() + } + if (hasPostponedLambdas) { + if (hasDirectPreviousNode) { + lastNodes.push(unionNode) + } else { + addNewSimpleNode(unionNode) + } + } else { + return EdgeKind.Simple to null + } + return Pair(kind, unionNode) } fun exitConstExpresion(constExpression: FirConstExpression<*>): ConstExpressionNode { @@ -695,16 +749,16 @@ class ControlFlowGraphBuilder { // ------------------------------------------------------------------------------------------------------------------------- - private fun addNodeThatReturnsNothing(node: CFGNode<*>) { + private fun addNodeThatReturnsNothing(node: CFGNode<*>, preferredKind: EdgeKind = EdgeKind.Simple) { /* * `return` is temporary solution that is needed for init block * it will be replaced after correct implementation of CFG for class initialization */ val exitNode: CFGNode<*> = exitNodes.top() - addNodeWithJump(node, exitNode) + addNodeWithJump(node, exitNode, preferredKind) } - private fun addNodeWithJump(node: CFGNode<*>, targetNode: CFGNode<*>?) { + private fun addNodeWithJump(node: CFGNode<*>, targetNode: CFGNode<*>?, preferredKind: EdgeKind = EdgeKind.Simple) { addEdge(lastNodes.pop(), node) if (targetNode != null) { addEdge(node, targetNode) @@ -714,9 +768,9 @@ class ControlFlowGraphBuilder { lastNodes.push(stub) } - private fun addNewSimpleNode(newNode: CFGNode<*>, isDead: Boolean = false): CFGNode<*> { + private fun addNewSimpleNode(newNode: CFGNode<*>, isDead: Boolean = false, preferredKind: EdgeKind = EdgeKind.Simple): CFGNode<*> { val oldNode = lastNodes.pop() - addEdge(oldNode, newNode, isDead = isDead) + addEdge(oldNode, newNode, isDead = isDead, preferredKind = preferredKind) lastNodes.push(newNode) return oldNode } @@ -726,8 +780,14 @@ class ControlFlowGraphBuilder { return addNewSimpleNode(newNode, isDead) } - private fun addEdge(from: CFGNode<*>, to: CFGNode<*>, propagateDeadness: Boolean = true, isDead: Boolean = false) { - val kind = if (isDead || from.isDead || to.isDead) EdgeKind.Dead else EdgeKind.Simple + private fun addEdge( + from: CFGNode<*>, + to: CFGNode<*>, + propagateDeadness: Boolean = true, + isDead: Boolean = false, + preferredKind: EdgeKind = EdgeKind.Simple + ) { + val kind = if (isDead || from.isDead || to.isDead) EdgeKind.Dead else preferredKind CFGNode.addEdge(from, to, kind, propagateDeadness) } @@ -740,5 +800,6 @@ class ControlFlowGraphBuilder { fun reset() { exitsOfAnonymousFunctions.clear() + exitsFromCompletedPostponedAnonymousFunctions.clear() } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt index 34cfcb4f44d..3bb52d7db3a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.resolve.dfa.cfg +import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* @@ -187,3 +188,6 @@ fun ControlFlowGraphBuilder.createPostponedLambdaEnterNode(fir: FirAnonymousFunc fun ControlFlowGraphBuilder.createAnonymousObjectExitNode(fir: FirAnonymousObject): AnonymousObjectExitNode = AnonymousObjectExitNode(graph, fir, levelCounter, createId()) + +fun ControlFlowGraphBuilder.createUnionFunctionCallArgumentsNode(fir: FirElement): UnionFunctionCallArgumentsNode = + UnionFunctionCallArgumentsNode(graph, fir, levelCounter, createId()) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt index e5b73718fad..ea27b1cc43e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt @@ -92,13 +92,19 @@ class FirControlFlowGraphRenderVisitor( } val attributes = mutableListOf() attributes += "label=\"${it.render().replace("\"", "")}\"" - if (it == enterNode || it == exitNode) { + + fun fillColor(color: String) { attributes += "style=\"filled\"" - attributes += "fillcolor=red" + attributes += "fillcolor=$color" + } + + if (it == enterNode || it == exitNode) { + fillColor("red") } if (it.isDead) { - attributes += "style=\"filled\"" - attributes += "fillcolor=gray" + fillColor("gray") + } else if (it is UnionFunctionCallArgumentsNode) { + fillColor("yellow") } println(indices.getValue(it), attributes.joinToString(separator = " ", prefix = " [", postfix = "];")) if (it is ExitNodeMarker) { @@ -218,6 +224,8 @@ private fun CFGNode<*>.render(): String = is AnonymousObjectExitNode -> "Exit anonymous object" + is UnionFunctionCallArgumentsNode -> "Call arguments union" + else -> TODO(this@render.toString()) }, ) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt index dc6951a051d..02b5b49e726 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt @@ -45,7 +45,9 @@ class FirCallCompleter( private val inferenceSession get() = inferenceComponents.inferenceSession - fun completeCall(call: T, expectedTypeRef: FirTypeRef?): T + data class CompletionResult(val result: T, val callCompleted: Boolean) + + fun completeCall(call: T, expectedTypeRef: FirTypeRef?): CompletionResult where T : FirResolvable, T : FirStatement { val typeRef = typeFromCallee(call) if (typeRef.type is ConeKotlinErrorType) { @@ -62,10 +64,10 @@ class FirCallCompleter( call } inferenceSession.addErrorCall(errorCall) - return errorCall + return CompletionResult(errorCall, true) } - val candidate = call.candidate() ?: return call + val candidate = call.candidate() ?: return CompletionResult(call, true) val initialSubstitutor = candidate.substitutor val initialType = initialSubstitutor.substituteOrSelf(typeRef.type) @@ -101,10 +103,10 @@ class FirCallCompleter( null ) inferenceSession.addCompetedCall(completedCall) - completedCall + CompletionResult(completedCall, true) } else { inferenceSession.addPartiallyResolvedCall(call) - call + CompletionResult(call, false) } } @@ -114,7 +116,7 @@ class FirCallCompleter( } val approximatedCall = call.transformSingle(integerOperatorsTypeUpdater, null) inferenceSession.addPartiallyResolvedCall(approximatedCall) - approximatedCall + CompletionResult(approximatedCall, false) } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt index 3dca1e6cb6e..a67cc88d352 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt @@ -122,7 +122,7 @@ class FirSyntheticCallGenerator( this.argumentList = argumentList } - val argument = callCompleter.completeCall(fakeCallElement, expectedTypeRef).argument + val argument = callCompleter.completeCall(fakeCallElement, expectedTypeRef).result.argument return ((argument as? FirVarargArgumentsExpression)?.arguments?.get(0) ?: argument) as FirCallableReferenceAccess? } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt index 65c59aff7be..7fd51f89ddb 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt @@ -63,19 +63,19 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran @Suppress("NAME_SHADOWING") var whenExpression = whenExpression.transformSubject(transformer, ResolutionMode.ContextIndependent) - when { - whenExpression.branches.isEmpty() -> { - } + val callCompleted = when { + whenExpression.branches.isEmpty() -> true whenExpression.isOneBranch() -> { whenExpression = whenExpression.transformBranches(transformer, ResolutionMode.ContextIndependent) whenExpression.resultType = whenExpression.branches.first().result.resultType + true } else -> { whenExpression = whenExpression.transformBranches(transformer, ResolutionMode.ContextDependent) whenExpression = syntheticCallGenerator.generateCalleeForWhenExpression(whenExpression) ?: run { whenExpression = whenExpression.transformSingle(whenExhaustivenessTransformer, null) - dataFlowAnalyzer.exitWhenExpression(whenExpression) + dataFlowAnalyzer.exitWhenExpression(whenExpression, callCompleted = true) whenExpression.resultType = buildErrorTypeRef { diagnostic = FirSimpleDiagnostic("Can't resolve when expression", DiagnosticKind.InferenceError) } @@ -83,11 +83,13 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran } val expectedTypeRef = data.expectedType - whenExpression = callCompleter.completeCall(whenExpression, expectedTypeRef) + val completionResult = callCompleter.completeCall(whenExpression, expectedTypeRef) + whenExpression = completionResult.result + completionResult.callCompleted } } whenExpression = whenExpression.transformSingle(whenExhaustivenessTransformer, null) - dataFlowAnalyzer.exitWhenExpression(whenExpression) + dataFlowAnalyzer.exitWhenExpression(whenExpression, callCompleted) whenExpression = whenExpression.replaceReturnTypeIfNotExhaustive() whenExpression.compose() } @@ -139,14 +141,18 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran dataFlowAnalyzer.exitTryMainBlock(tryExpression) tryExpression.transformCatches(this, ResolutionMode.ContextDependent) + var callCompleted: Boolean = false @Suppress("NAME_SHADOWING") var result = syntheticCallGenerator.generateCalleeForTryExpression(tryExpression)?.let { val expectedTypeRef = data.expectedType - callCompleter.completeCall(it, expectedTypeRef) + val completionResult = callCompleter.completeCall(it, expectedTypeRef) + callCompleted = completionResult.callCompleted + completionResult.result } ?: run { tryExpression.resultType = buildErrorTypeRef { diagnostic = FirSimpleDiagnostic("Can't resolve try expression", DiagnosticKind.InferenceError) } + callCompleted = true tryExpression } @@ -157,7 +163,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran } else { result } - dataFlowAnalyzer.exitTryExpression(result) + dataFlowAnalyzer.exitTryExpression(result, callCompleted) return result.compose() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 6b767b6740e..bd13d40c84d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -134,7 +134,7 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : // NB: here we can get raw expression because of dropped qualifiers (see transform callee), // so candidate existence must be checked before calling completion if (transformedCallee is FirQualifiedAccessExpression && transformedCallee.candidate() != null) { - callCompleter.completeCall(transformedCallee, data.expectedType) + callCompleter.completeCall(transformedCallee, data.expectedType).result } else { transformedCallee } @@ -153,11 +153,12 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : storeTypeFromCallee(functionCall) } if (functionCall.calleeReference !is FirSimpleNamedReference) return functionCall.compose() + dataFlowAnalyzer.enterFunctionCall(functionCall) functionCall.annotations.forEach { it.accept(this, data) } functionCall.transform(InvocationKindTransformer, null) functionCall.transformTypeArguments(transformer, ResolutionMode.ContextIndependent) val expectedTypeRef = data.expectedType - val completeInference = + val (completeInference, callCompleted) = try { val initialExplicitReceiver = functionCall.explicitReceiver val resultExpression = callResolver.resolveCallAndSelectCandidate(functionCall) @@ -167,8 +168,9 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : callCompleter.completeCall(resultExplicitReceiver, noExpectedType) } val completionResult = callCompleter.completeCall(resultExpression, expectedTypeRef) - if (completionResult.typeRef is FirErrorTypeRef) { - completionResult.argumentList.transformArguments(transformer, ResolutionMode.LambdaResolution(null)) + + if (completionResult.result.typeRef is FirErrorTypeRef) { + completionResult.result.argumentList.transformArguments(transformer, ResolutionMode.LambdaResolution(null)) } completionResult } catch (e: ProcessCanceledException) { @@ -177,7 +179,7 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : throw RuntimeException("While resolving call ${functionCall.render()}", e) } - dataFlowAnalyzer.exitFunctionCall(completeInference) + dataFlowAnalyzer.exitFunctionCall(completeInference, callCompleted) return completeInference.compose() } @@ -365,16 +367,20 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : checkNotNullCall.argumentList.transformArguments(transformer, ResolutionMode.ContextDependent) + var callCompleted: Boolean = false val result = components.syntheticCallGenerator.generateCalleeForCheckNotNullCall(checkNotNullCall)?.let { - callCompleter.completeCall(it, data.expectedType) + val completionResult = callCompleter.completeCall(it, data.expectedType) + callCompleted = completionResult.callCompleted + completionResult.result } ?: run { checkNotNullCall.resultType = buildErrorTypeRef { diagnostic = FirSimpleDiagnostic("Can't resolve !! operator call", DiagnosticKind.InferenceError) } + callCompleted = true checkNotNullCall } - dataFlowAnalyzer.exitCheckNotNullCall(result) + dataFlowAnalyzer.exitCheckNotNullCall(result, callCompleted) return result.compose() } @@ -408,7 +414,7 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : variableAssignment.annotations.forEach { it.accept(this, data) } val resolvedAssignment = callResolver.resolveVariableAccessAndSelectCandidate(variableAssignment) val result = if (resolvedAssignment is FirVariableAssignment) { - val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType) // TODO: check + val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType).result // TODO: check val expectedType = components.typeFromCallee(completeAssignment) completeAssignment.transformRValue(transformer, withExpectedType(expectedType)) .transformRValue(integerLiteralTypeApproximator, expectedType.coneTypeSafe()) @@ -598,7 +604,7 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : } val result = callResolver.resolveDelegatingConstructorCall(delegatedConstructorCall, symbol, typeArguments) ?: return delegatedConstructorCall.compose() - return callCompleter.completeCall(result, noExpectedType).compose() + return callCompleter.completeCall(result, noExpectedType).result.compose() } // ------------------------------------------------------------------------------------------------ diff --git a/compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.dot b/compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.dot new file mode 100644 index 00000000000..97877ba6141 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.dot @@ -0,0 +1,451 @@ +digraph flowFromInplaceLambda_kt { + graph [nodesep=3] + node [shape=box penwidth=2] + edge [penwidth=2] + + subgraph cluster_0 { + color=red + 0 [label="Enter function takeInt" style="filled" fillcolor=red]; + 1 [label="Exit function takeInt" style="filled" fillcolor=red]; + } + + 0 -> {1}; + + subgraph cluster_1 { + color=red + 2 [label="Enter function select" style="filled" fillcolor=red]; + 3 [label="Access variable R|/x|"]; + 4 [label="Const: Int(0)"]; + 5 [label="Function call: R|/x|.R|FakeOverride|(...)"]; + 6 [label="Jump: ^select R|/x|.R|FakeOverride|(Int(0))"]; + 7 [label="Stub" style="filled" fillcolor=gray]; + 8 [label="Exit function select" style="filled" fillcolor=red]; + } + + 2 -> {3}; + 3 -> {4}; + 4 -> {5}; + 5 -> {6}; + 6 -> {8}; + 6 -> {7} [style=dotted]; + 7 -> {8} [style=dotted]; + + subgraph cluster_2 { + color=red + 9 [label="Enter function id" style="filled" fillcolor=red]; + 10 [label="Access variable R|/x|"]; + 11 [label="Jump: ^id R|/x|"]; + 12 [label="Stub" style="filled" fillcolor=gray]; + 13 [label="Exit function id" style="filled" fillcolor=red]; + } + + 9 -> {10}; + 10 -> {11}; + 11 -> {13}; + 11 -> {12} [style=dotted]; + 12 -> {13} [style=dotted]; + + subgraph cluster_3 { + color=red + 14 [label="Enter function materialize" style="filled" fillcolor=red]; + 15 [label="Const: Null(null)"]; + 16 [label="Check not null: Null(null)!!"]; + 17 [label="Jump: ^materialize Null(null)!!"]; + 18 [label="Stub" style="filled" fillcolor=gray]; + 19 [label="Exit function materialize" style="filled" fillcolor=red]; + } + + 14 -> {15}; + 15 -> {16}; + 16 -> {17}; + 17 -> {19}; + 17 -> {18} [style=dotted]; + 18 -> {19} [style=dotted]; + + subgraph cluster_4 { + color=red + 20 [label="Enter function myRun" style="filled" fillcolor=red]; + 21 [label="Function call: R|/block|.R|FakeOverride|()"]; + 22 [label="Jump: ^myRun R|/block|.R|FakeOverride|()"]; + 23 [label="Stub" style="filled" fillcolor=gray]; + 24 [label="Exit function myRun" style="filled" fillcolor=red]; + } + + 20 -> {21}; + 21 -> {22}; + 22 -> {24}; + 22 -> {23} [style=dotted]; + 23 -> {24} [style=dotted]; + + subgraph cluster_5 { + color=red + 25 [label="Enter function test_1" style="filled" fillcolor=red]; + 26 [label="Postponed enter to lambda"]; + subgraph cluster_6 { + color=blue + 27 [label="Enter function anonymousFunction"]; + 28 [label="Access variable R|/x|"]; + 29 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 30 [label="Exit function anonymousFunction"]; + } + 31 [label="Call arguments union" style="filled" fillcolor=yellow]; + 32 [label="Postponed exit from lambda"]; + 33 [label="Function call: R|kotlin/run|(...)"]; + 34 [label="Access variable R|/x|"]; + 35 [label="Function call: R|/takeInt|(...)"]; + 36 [label="Exit function test_1" style="filled" fillcolor=red]; + } + + 25 -> {26}; + 26 -> {27}; + 26 -> {32} [color=red]; + 27 -> {28}; + 28 -> {29}; + 29 -> {30}; + 30 -> {32} [color=green]; + 30 -> {31} [color=red]; + 31 -> {33} [color=red]; + 32 -> {33} [color=green]; + 33 -> {34}; + 34 -> {35}; + 35 -> {36}; + + subgraph cluster_7 { + color=red + 37 [label="Enter function test_2" style="filled" fillcolor=red]; + 38 [label="Postponed enter to lambda"]; + subgraph cluster_8 { + color=blue + 39 [label="Enter function anonymousFunction"]; + 40 [label="Access variable R|/y|"]; + 41 [label="Function call: R|/y|.#()"]; + 42 [label="Access variable R|/x|"]; + 43 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 44 [label="Exit function anonymousFunction"]; + } + 45 [label="Postponed exit from lambda"]; + 46 [label="Function call: R|kotlin/run|(...)"]; + 47 [label="Call arguments union" style="filled" fillcolor=yellow]; + 48 [label="Function call: R|/id|(...)"]; + 49 [label="Access variable R|/y|"]; + 50 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 51 [label="Postponed enter to lambda"]; + subgraph cluster_9 { + color=blue + 52 [label="Enter function anonymousFunction"]; + 53 [label="Access variable R|/x|"]; + 54 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 55 [label="Access variable R|/y|"]; + 56 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 57 [label="Const: Int(1)"]; + 58 [label="Exit function anonymousFunction"]; + } + 59 [label="Postponed exit from lambda"]; + 60 [label="Function call: R|kotlin/run|(...)"]; + 61 [label="Call arguments union" style="filled" fillcolor=yellow]; + 62 [label="Function call: R|/select|(...)"]; + 63 [label="Variable declaration: lval a: R|kotlin/Int|"]; + 64 [label="Access variable R|/x|"]; + 65 [label="Function call: R|/takeInt|(...)"]; + 66 [label="Access variable R|/y|"]; + 67 [label="Function call: R|/takeInt|(...)"]; + 68 [label="Access variable R|/a|"]; + 69 [label="Function call: R|/takeInt|(...)"]; + 70 [label="Exit function test_2" style="filled" fillcolor=red]; + } + + 37 -> {38}; + 38 -> {39}; + 38 -> {45} [color=red]; + 39 -> {40}; + 40 -> {41}; + 41 -> {42}; + 42 -> {43}; + 43 -> {44}; + 44 -> {45} [color=green]; + 44 -> {47} [color=red]; + 45 -> {46}; + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + 49 -> {50}; + 50 -> {51}; + 51 -> {52}; + 51 -> {59} [color=red]; + 52 -> {53}; + 53 -> {54}; + 54 -> {55}; + 55 -> {56}; + 56 -> {57}; + 57 -> {58}; + 58 -> {59} [color=green]; + 58 -> {61} [color=red]; + 59 -> {60}; + 60 -> {61}; + 61 -> {62}; + 62 -> {63}; + 63 -> {64}; + 64 -> {65}; + 65 -> {66}; + 66 -> {67}; + 67 -> {68}; + 68 -> {69}; + 69 -> {70}; + + subgraph cluster_10 { + color=red + 71 [label="Enter function test_3" style="filled" fillcolor=red]; + 72 [label="Postponed enter to lambda"]; + subgraph cluster_11 { + color=blue + 73 [label="Enter function anonymousFunction"]; + 74 [label="Access variable R|/y|"]; + 75 [label="Function call: R|/y|.#()"]; + 76 [label="Access variable R|/x|"]; + 77 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 78 [label="Function call: R|/materialize|()"]; + 79 [label="Exit function anonymousFunction"]; + } + 80 [label="Postponed exit from lambda"]; + 81 [label="Function call: R|kotlin/run|(...)"]; + 82 [label="Function call: R|/id|(...)"]; + 83 [label="Postponed enter to lambda"]; + subgraph cluster_12 { + color=blue + 84 [label="Enter function anonymousFunction"]; + 85 [label="Access variable R|/y|"]; + 86 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 87 [label="Access variable R|/x|"]; + 88 [label="Function call: R|/x|.#()"]; + 89 [label="Access variable R|/y|"]; + 90 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 91 [label="Const: Int(1)"]; + 92 [label="Exit function anonymousFunction"]; + } + 93 [label="Postponed exit from lambda"]; + 94 [label="Function call: R|kotlin/run|(...)"]; + 95 [label="Call arguments union" style="filled" fillcolor=yellow]; + 96 [label="Function call: R|/select|(...)"]; + 97 [label="Variable declaration: lval a: R|kotlin/Int|"]; + 98 [label="Access variable R|/x|"]; + 99 [label="Function call: R|/takeInt|(...)"]; + 100 [label="Access variable R|/y|"]; + 101 [label="Function call: R|/takeInt|(...)"]; + 102 [label="Access variable R|/a|"]; + 103 [label="Function call: R|/takeInt|(...)"]; + 104 [label="Exit function test_3" style="filled" fillcolor=red]; + } + + 71 -> {72}; + 72 -> {73}; + 72 -> {80} [color=red]; + 73 -> {74}; + 74 -> {75}; + 75 -> {76}; + 76 -> {77}; + 77 -> {78}; + 78 -> {79}; + 79 -> {80} [color=green]; + 79 -> {95} [color=red]; + 80 -> {81}; + 81 -> {82}; + 82 -> {83}; + 83 -> {84}; + 83 -> {93} [color=red]; + 84 -> {85}; + 85 -> {86}; + 86 -> {87}; + 87 -> {88}; + 88 -> {89}; + 89 -> {90}; + 90 -> {91}; + 91 -> {92}; + 92 -> {93} [color=green]; + 92 -> {95} [color=red]; + 93 -> {94}; + 94 -> {95}; + 95 -> {96}; + 96 -> {97}; + 97 -> {98}; + 98 -> {99}; + 99 -> {100}; + 100 -> {101}; + 101 -> {102}; + 102 -> {103}; + 103 -> {104}; + + subgraph cluster_13 { + color=red + 105 [label="Enter function test_4" style="filled" fillcolor=red]; + 106 [label="Postponed enter to lambda"]; + 107 [label="Postponed exit from lambda"]; + 108 [label="Function call: R|/myRun|(...)"]; + 109 [label="Function call: R|/id|(...)"]; + 110 [label="Access variable R|/y|"]; + 111 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 112 [label="Postponed enter to lambda"]; + 113 [label="Postponed exit from lambda"]; + 114 [label="Function call: R|/myRun|(...)"]; + 115 [label="Function call: R|/select|(...)"]; + 116 [label="Variable declaration: lval a: R|kotlin/Int|"]; + 117 [label="Access variable R|/x|"]; + 118 [label="Access variable R|/x|"]; + 119 [label="Access variable R|/x|"]; + 120 [label="Function call: #(...)"]; + 121 [label="Access variable R|/y|"]; + 122 [label="Function call: R|/takeInt|(...)"]; + 123 [label="Access variable R|/a|"]; + 124 [label="Function call: R|/takeInt|(...)"]; + 125 [label="Exit function test_4" style="filled" fillcolor=red]; + } + + 105 -> {106}; + 106 -> {107 107} [color=green]; + 107 -> {108}; + 108 -> {109}; + 109 -> {110}; + 110 -> {111}; + 111 -> {112}; + 112 -> {113 113} [color=green]; + 113 -> {114}; + 114 -> {115}; + 115 -> {116}; + 116 -> {117}; + 117 -> {118}; + 118 -> {119}; + 119 -> {120}; + 120 -> {121}; + 121 -> {122}; + 122 -> {123}; + 123 -> {124}; + 124 -> {125}; + + subgraph cluster_14 { + color=red + 126 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 127 [label="Access variable R|/y|"]; + 128 [label="Function call: R|/y|.#()"]; + 129 [label="Access variable R|/x|"]; + 130 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 131 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + + 126 -> {127}; + 127 -> {128}; + 128 -> {129}; + 129 -> {130}; + 130 -> {131}; + + subgraph cluster_15 { + color=red + 132 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 133 [label="Access variable R|/x|"]; + 134 [label="Function call: R|/x|.#()"]; + 135 [label="Access variable R|/y|"]; + 136 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 137 [label="Const: Int(1)"]; + 138 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + + 132 -> {133}; + 133 -> {134}; + 134 -> {135}; + 135 -> {136}; + 136 -> {137}; + 137 -> {138}; + + subgraph cluster_16 { + color=red + 139 [label="Enter function test_5" style="filled" fillcolor=red]; + 140 [label="Postponed enter to lambda"]; + subgraph cluster_17 { + color=blue + 141 [label="Enter function anonymousFunction"]; + 142 [label="Function call: R|/materialize|()"]; + 143 [label="Exit function anonymousFunction"]; + } + 144 [label="Postponed exit from lambda"]; + 145 [label="Function call: R|kotlin/run|(...)"]; + 146 [label="Postponed enter to lambda"]; + subgraph cluster_18 { + color=blue + 147 [label="Enter function anonymousFunction"]; + 148 [label="Function call: R|/materialize|()"]; + 149 [label="Exit function anonymousFunction"]; + } + 150 [label="Postponed exit from lambda"]; + 151 [label="Function call: R|kotlin/run|(...)"]; + 152 [label="Call arguments union" style="filled" fillcolor=yellow]; + 153 [label="Function call: R|/select|(...)"]; + 154 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 155 [label="Access variable R|/x|"]; + 156 [label="Function call: R|/takeInt|(...)"]; + 157 [label="Exit function test_5" style="filled" fillcolor=red]; + } + + 139 -> {140}; + 140 -> {141}; + 140 -> {144} [color=red]; + 141 -> {142}; + 142 -> {143}; + 143 -> {144} [color=green]; + 143 -> {152} [color=red]; + 144 -> {145}; + 145 -> {146}; + 146 -> {147}; + 146 -> {150} [color=red]; + 147 -> {148}; + 148 -> {149}; + 149 -> {150} [color=green]; + 149 -> {152} [color=red]; + 150 -> {151}; + 151 -> {152}; + 152 -> {153}; + 153 -> {154}; + 154 -> {155}; + 155 -> {156}; + 156 -> {157}; + + subgraph cluster_19 { + color=red + 158 [label="Enter function test_6" style="filled" fillcolor=red]; + 159 [label="Postponed enter to lambda"]; + 160 [label="Postponed exit from lambda"]; + 161 [label="Function call: R|/myRun|(...)"]; + 162 [label="Function call: R|/id|(...)"]; + 163 [label="Variable declaration: lval x: R|kotlin/String|"]; + 164 [label="Exit function test_6" style="filled" fillcolor=red]; + } + + 158 -> {159}; + 159 -> {160 160} [color=green]; + 160 -> {161}; + 161 -> {162}; + 162 -> {163}; + 163 -> {164}; + + subgraph cluster_20 { + color=red + 165 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 166 [label="Postponed enter to lambda"]; + subgraph cluster_21 { + color=blue + 167 [label="Enter function anonymousFunction"]; + 168 [label="Function call: R|/materialize|()"]; + 169 [label="Exit function anonymousFunction"]; + } + 170 [label="Postponed exit from lambda"]; + 171 [label="Function call: R|kotlin/run|(...)"]; + 172 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + + 165 -> {166}; + 166 -> {167}; + 166 -> {170} [color=red]; + 167 -> {168}; + 168 -> {169}; + 169 -> {170} [color=green]; + 170 -> {171}; + 171 -> {172}; + +} diff --git a/compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.kt b/compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.kt new file mode 100644 index 00000000000..d965d81be19 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.kt @@ -0,0 +1,93 @@ +// !DUMP_CFG + +fun takeInt(x: Int) {} + +fun select(vararg x: K): K = x[0] +fun id(x: T): T = x +fun materialize(): K = null!! + +fun myRun(block: () -> R): R = block() + +fun test_1(x: Any) { + run { + x as Int + } + takeInt(x) // OK +} + +fun test_2(x: Any, y: Any) { + val a = select( + id( + run { + y.inc() // Bad + x as Int + } + ), + y as Int, + run { + x.inc() // Should be "Bad" but "OK" is fine + y.inc() // OK + 1 + } + ) + takeInt(x) // OK + takeInt(y) // OK + takeInt(a) // OK +} + +fun test_3(x: Any, y: Any) { + val a = select( + id( + run { + y.inc() // Bad + x as Int + materialize() + } + ), + run { + y as Int + x.inc() // Bad + y.inc() // OK + 1 + } + ) + takeInt(x) // OK + takeInt(y) // OK + takeInt(a) // OK +} + +fun test_4(x: Any, y: Any) { + val a = select( + id( + myRun { + y.inc() // Bad + x as Int + } + ), + y as Int, + myRun { + x.inc() // Bad + y.inc() // OK + 1 + } + + ) + takeInt(x) // Bad + takeInt(y) // OK + takeInt(a) // Bad +} + +fun test_5() { + val x: Int = select(run { materialize() }, run { materialize() }) + takeInt(x) +} + +fun test_6() { + val x: String = id( + myRun { + run { + materialize() + } + } + ) +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.txt b/compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.txt new file mode 100644 index 00000000000..6311423fb48 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.txt @@ -0,0 +1,88 @@ +FILE: flowFromInplaceLambda.kt + public final fun takeInt(x: R|kotlin/Int|): R|kotlin/Unit| { + } + public final fun select(vararg x: R|kotlin/Array|): R|K| { + ^select R|/x|.R|FakeOverride|(Int(0)) + } + public final fun id(x: R|T|): R|T| { + ^id R|/x| + } + public final fun materialize(): R|K| { + ^materialize Null(null)!! + } + public final fun myRun(block: R|() -> R|): R|R| { + ^myRun R|/block|.R|FakeOverride|() + } + public final fun test_1(x: R|kotlin/Any|): R|kotlin/Unit| { + R|kotlin/run|( = run@fun (): R|kotlin/Int| { + ^ (R|/x| as R|kotlin/Int|) + } + ) + R|/takeInt|(R|/x|) + } + public final fun test_2(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + lval a: R|kotlin/Int| = R|/select|(vararg(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Int| { + R|/y|.#() + ^ (R|/x| as R|kotlin/Int|) + } + )), (R|/y| as R|kotlin/Int|), R|kotlin/run|( = run@fun (): R|kotlin/Int| { + R|/x|.R|kotlin/Int.inc|() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))) + R|/takeInt|(R|/x|) + R|/takeInt|(R|/y|) + R|/takeInt|(R|/a|) + } + public final fun test_3(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + lval a: R|kotlin/Int| = R|/select|(vararg(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Int| { + R|/y|.#() + (R|/x| as R|kotlin/Int|) + ^ R|/materialize|() + } + )), R|kotlin/run|( = run@fun (): R|kotlin/Int| { + (R|/y| as R|kotlin/Int|) + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))) + R|/takeInt|(R|/x|) + R|/takeInt|(R|/y|) + R|/takeInt|(R|/a|) + } + public final fun test_4(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + lval a: R|kotlin/Int| = R|/select|(vararg(R|/id|(R|/myRun|( = myRun@fun (): R|kotlin/Int| { + R|/y|.#() + ^ (R|/x| as R|kotlin/Int|) + } + )), (R|/y| as R|kotlin/Int|), R|/myRun|( = myRun@fun (): R|kotlin/Int| { + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))) + #(R|/x|) + R|/takeInt|(R|/y|) + R|/takeInt|(R|/a|) + } + public final fun test_5(): R|kotlin/Unit| { + lval x: R|kotlin/Int| = R|/select|(vararg(R|kotlin/run|( = run@fun (): R|kotlin/Int| { + ^ R|/materialize|() + } + ), R|kotlin/run|( = run@fun (): R|kotlin/Int| { + ^ R|/materialize|() + } + ))) + R|/takeInt|(R|/x|) + } + public final fun test_6(): R|kotlin/Unit| { + lval x: R|kotlin/String| = R|/id|(R|/myRun|( = myRun@fun (): R|kotlin/String| { + ^ R|kotlin/run|( = run@fun (): R|kotlin/String| { + ^ R|/materialize|() + } + ) + } + )) + } diff --git a/compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.dot b/compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.dot new file mode 100644 index 00000000000..45bcfeceaef --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.dot @@ -0,0 +1,196 @@ +digraph inplaceLambdaInControlFlowExpressions_kt { + graph [nodesep=3] + node [shape=box penwidth=2] + edge [penwidth=2] + + subgraph cluster_0 { + color=red + 0 [label="Enter function materialize" style="filled" fillcolor=red]; + 1 [label="Const: Null(null)"]; + 2 [label="Check not null: Null(null)!!"]; + 3 [label="Jump: ^materialize Null(null)!!"]; + 4 [label="Stub" style="filled" fillcolor=gray]; + 5 [label="Exit function materialize" style="filled" fillcolor=red]; + } + + 0 -> {1}; + 1 -> {2}; + 2 -> {3}; + 3 -> {5}; + 3 -> {4} [style=dotted]; + 4 -> {5} [style=dotted]; + + subgraph cluster_1 { + color=red + 6 [label="Enter function test_1" style="filled" fillcolor=red]; + subgraph cluster_2 { + color=blue + 7 [label="Enter when"]; + subgraph cluster_3 { + color=blue + 8 [label="Enter when branch condition "]; + 9 [label="Const: Boolean(true)"]; + 10 [label="Exit when branch condition"]; + } + subgraph cluster_4 { + color=blue + 11 [label="Enter when branch condition else"]; + 12 [label="Exit when branch condition"]; + } + 13 [label="Enter when branch result"]; + subgraph cluster_5 { + color=blue + 14 [label="Enter block"]; + 15 [label="Const: String()"]; + 16 [label="Exit block"]; + } + 17 [label="Exit when branch result"]; + 18 [label="Enter when branch result"]; + subgraph cluster_6 { + color=blue + 19 [label="Enter block"]; + 20 [label="Postponed enter to lambda"]; + subgraph cluster_7 { + color=blue + 21 [label="Enter function anonymousFunction"]; + 22 [label="Function call: R|/materialize|()"]; + 23 [label="Exit function anonymousFunction"]; + } + 24 [label="Postponed exit from lambda"]; + 25 [label="Function call: R|kotlin/run|(...)"]; + 26 [label="Exit block"]; + } + 27 [label="Exit when branch result"]; + 28 [label="Exit when"]; + } + 29 [label="Call arguments union" style="filled" fillcolor=yellow]; + 30 [label="Variable declaration: lval x: R|kotlin/String|"]; + 31 [label="Exit function test_1" style="filled" fillcolor=red]; + } + + 6 -> {7}; + 7 -> {8}; + 8 -> {9}; + 9 -> {10}; + 10 -> {18 11}; + 11 -> {12}; + 12 -> {13}; + 13 -> {14}; + 14 -> {15}; + 15 -> {16}; + 16 -> {17}; + 17 -> {28}; + 18 -> {19}; + 19 -> {20}; + 20 -> {21}; + 20 -> {24} [color=red]; + 21 -> {22}; + 22 -> {23}; + 23 -> {24} [color=green]; + 23 -> {29} [color=red]; + 24 -> {25}; + 25 -> {26}; + 26 -> {27}; + 27 -> {28}; + 28 -> {29}; + 29 -> {30}; + 30 -> {31}; + + subgraph cluster_8 { + color=red + 32 [label="Enter function test_2" style="filled" fillcolor=red]; + subgraph cluster_9 { + color=blue + 33 [label="Try expression enter"]; + subgraph cluster_10 { + color=blue + 34 [label="Try main block enter"]; + subgraph cluster_11 { + color=blue + 35 [label="Enter block"]; + 36 [label="Postponed enter to lambda"]; + subgraph cluster_12 { + color=blue + 37 [label="Enter function anonymousFunction"]; + 38 [label="Function call: R|/materialize|()"]; + 39 [label="Exit function anonymousFunction"]; + } + 40 [label="Postponed exit from lambda"]; + 41 [label="Function call: R|kotlin/run|(...)"]; + 42 [label="Exit block"]; + } + 43 [label="Try main block exit"]; + } + subgraph cluster_13 { + color=blue + 44 [label="Catch enter"]; + subgraph cluster_14 { + color=blue + 45 [label="Enter block"]; + 46 [label="Const: String()"]; + 47 [label="Exit block"]; + } + 48 [label="Catch exit"]; + } + 49 [label="Try expression exit"]; + } + 50 [label="Call arguments union" style="filled" fillcolor=yellow]; + 51 [label="Variable declaration: lval x: R|kotlin/String|"]; + 52 [label="Exit function test_2" style="filled" fillcolor=red]; + } + + 32 -> {33}; + 33 -> {34}; + 34 -> {52 44 35}; + 35 -> {36}; + 36 -> {37}; + 36 -> {40} [color=red]; + 37 -> {38}; + 38 -> {39}; + 39 -> {40} [color=green]; + 39 -> {50} [color=red]; + 40 -> {41}; + 41 -> {42}; + 42 -> {43}; + 43 -> {49}; + 44 -> {52 45}; + 45 -> {46}; + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + 49 -> {50}; + 50 -> {51}; + 51 -> {52}; + + subgraph cluster_15 { + color=red + 53 [label="Enter function test_3" style="filled" fillcolor=red]; + 54 [label="Postponed enter to lambda"]; + subgraph cluster_16 { + color=blue + 55 [label="Enter function anonymousFunction"]; + 56 [label="Function call: R|/materialize|()"]; + 57 [label="Exit function anonymousFunction"]; + } + 58 [label="Postponed exit from lambda"]; + 59 [label="Function call: R|kotlin/run|(...)"]; + 60 [label="Check not null: R|kotlin/run|(...)!!"]; + 61 [label="Call arguments union" style="filled" fillcolor=yellow]; + 62 [label="Variable declaration: lval x: R|kotlin/String|"]; + 63 [label="Exit function test_3" style="filled" fillcolor=red]; + } + + 53 -> {54}; + 54 -> {55}; + 54 -> {58} [color=red]; + 55 -> {56}; + 56 -> {57}; + 57 -> {58} [color=green]; + 57 -> {61} [color=red]; + 58 -> {59}; + 59 -> {60}; + 60 -> {61}; + 61 -> {62}; + 62 -> {63}; + +} diff --git a/compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.kt b/compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.kt new file mode 100644 index 00000000000..14b63637183 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.kt @@ -0,0 +1,25 @@ +// !DUMP_CFG + +fun materialize(): K = null!! + +fun test_1() { + val x = if (true) { + run { materialize() } + } else { + "" + } +} + +fun test_2() { + val x = try { + run { + materialize() + } + } catch (e: Exception) { + "" + } +} + +fun test_3() { + val x: String = run { materialize() }!! +} diff --git a/compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.txt b/compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.txt new file mode 100644 index 00000000000..5cefa8f9580 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.txt @@ -0,0 +1,36 @@ +FILE: inplaceLambdaInControlFlowExpressions.kt + public final fun materialize(): R|K| { + ^materialize Null(null)!! + } + public final fun test_1(): R|kotlin/Unit| { + lval x: R|kotlin/String| = when () { + Boolean(true) -> { + R|kotlin/run|( = run@fun (): R|kotlin/String| { + ^ R|/materialize|() + } + ) + } + else -> { + String() + } + } + + } + public final fun test_2(): R|kotlin/Unit| { + lval x: R|kotlin/String| = try { + R|kotlin/run|( = run@fun (): R|kotlin/String| { + ^ R|/materialize|() + } + ) + } + catch (e: R|kotlin/Exception|) { + String() + } + + } + public final fun test_3(): R|kotlin/Unit| { + lval x: R|kotlin/String| = R|kotlin/run|( = run@fun (): R|kotlin/String?| { + ^ R|/materialize|() + } + )!! + } diff --git a/compiler/fir/resolve/testData/resolve/cfg/returnValuesFromLambda.dot b/compiler/fir/resolve/testData/resolve/cfg/returnValuesFromLambda.dot index fe6eb6b64ad..07c459685a8 100644 --- a/compiler/fir/resolve/testData/resolve/cfg/returnValuesFromLambda.dot +++ b/compiler/fir/resolve/testData/resolve/cfg/returnValuesFromLambda.dot @@ -51,15 +51,16 @@ digraph returnValuesFromLambda_kt { 20 [label="Function call: R|/C.C|()"]; 21 [label="Exit function anonymousFunction"]; } - 22 [label="Postponed exit from lambda"]; - 23 [label="Function call: R|kotlin/run|(...)"]; - 24 [label="Variable declaration: lval x: R|A|"]; - 25 [label="Exit function test_1" style="filled" fillcolor=red]; + 22 [label="Call arguments union" style="filled" fillcolor=yellow]; + 23 [label="Postponed exit from lambda"]; + 24 [label="Function call: R|kotlin/run|(...)"]; + 25 [label="Variable declaration: lval x: R|A|"]; + 26 [label="Exit function test_1" style="filled" fillcolor=red]; } 4 -> {5}; 5 -> {6}; - 5 -> {22} [color=red]; + 5 -> {23} [color=red]; 6 -> {7}; 7 -> {8}; 8 -> {9}; @@ -76,72 +77,79 @@ digraph returnValuesFromLambda_kt { 18 -> {19} [style=dotted]; 19 -> {20}; 20 -> {21}; - 21 -> {22} [color=green]; - 22 -> {23}; - 23 -> {24}; + 21 -> {23} [color=green]; + 21 -> {22} [color=red]; + 22 -> {24} [color=red]; + 23 -> {24} [color=green]; 24 -> {25}; + 25 -> {26}; subgraph cluster_7 { color=red - 26 [label="Enter function test_2" style="filled" fillcolor=red]; - 27 [label="Postponed enter to lambda"]; + 27 [label="Enter function test_2" style="filled" fillcolor=red]; + 28 [label="Postponed enter to lambda"]; subgraph cluster_8 { color=blue - 28 [label="Enter function anonymousFunction"]; - 29 [label="Function call: R|/C.C|()"]; - 30 [label="Jump: ^@run R|/C.C|()"]; - 31 [label="Stub" style="filled" fillcolor=gray]; - 32 [label="Exit function anonymousFunction"]; + 29 [label="Enter function anonymousFunction"]; + 30 [label="Function call: R|/C.C|()"]; + 31 [label="Jump: ^@run R|/C.C|()"]; + 32 [label="Stub" style="filled" fillcolor=gray]; + 33 [label="Exit function anonymousFunction"]; } - 33 [label="Postponed exit from lambda"]; - 34 [label="Function call: R|kotlin/run|(...)"]; - 35 [label="Variable declaration: lval x: R|C|"]; - 36 [label="Exit function test_2" style="filled" fillcolor=red]; + 34 [label="Call arguments union" style="filled" fillcolor=yellow]; + 35 [label="Postponed exit from lambda"]; + 36 [label="Function call: R|kotlin/run|(...)"]; + 37 [label="Variable declaration: lval x: R|C|"]; + 38 [label="Exit function test_2" style="filled" fillcolor=red]; } - 26 -> {27}; 27 -> {28}; - 27 -> {33} [color=red]; 28 -> {29}; + 28 -> {35} [color=red]; 29 -> {30}; - 30 -> {32}; - 30 -> {31} [style=dotted]; + 30 -> {31}; + 31 -> {33}; 31 -> {32} [style=dotted]; - 32 -> {33} [color=green]; - 33 -> {34}; - 34 -> {35}; - 35 -> {36}; + 32 -> {33} [style=dotted]; + 33 -> {35} [color=green]; + 33 -> {34} [color=red]; + 34 -> {36} [color=red]; + 35 -> {36} [color=green]; + 36 -> {37}; + 37 -> {38}; subgraph cluster_9 { color=red - 37 [label="Enter function test_3" style="filled" fillcolor=red]; - 38 [label="Postponed enter to lambda"]; + 39 [label="Enter function test_3" style="filled" fillcolor=red]; + 40 [label="Postponed enter to lambda"]; subgraph cluster_10 { color=blue - 39 [label="Enter function anonymousFunction"]; - 40 [label="Jump: ^test_3 Unit"]; - 41 [label="Stub" style="filled" fillcolor=gray]; - 42 [label="Exit function anonymousFunction" style="filled" fillcolor=gray]; + 41 [label="Enter function anonymousFunction"]; + 42 [label="Jump: ^test_3 Unit"]; + 43 [label="Stub" style="filled" fillcolor=gray]; + 44 [label="Exit function anonymousFunction" style="filled" fillcolor=gray]; } - 43 [label="Postponed exit from lambda"]; - 44 [label="Function call: R|kotlin/run|(...)"]; - 45 [label="Stub" style="filled" fillcolor=gray]; - 46 [label="Variable declaration: lval x: R|kotlin/Nothing|" style="filled" fillcolor=gray]; - 47 [label="Exit function test_3" style="filled" fillcolor=red]; + 45 [label="Call arguments union" style="filled" fillcolor=gray]; + 46 [label="Postponed exit from lambda"]; + 47 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=gray]; + 48 [label="Stub" style="filled" fillcolor=gray]; + 49 [label="Variable declaration: lval x: R|kotlin/Nothing|" style="filled" fillcolor=gray]; + 50 [label="Exit function test_3" style="filled" fillcolor=red]; } - 37 -> {38}; - 38 -> {39}; - 38 -> {43} [color=red]; 39 -> {40}; - 40 -> {47}; - 40 -> {41} [style=dotted]; - 41 -> {42} [style=dotted]; - 42 -> {43} [color=green]; - 43 -> {44}; - 44 -> {47}; + 40 -> {41}; + 40 -> {46} [color=red]; + 41 -> {42}; + 42 -> {50}; + 42 -> {43} [style=dotted]; + 43 -> {44} [style=dotted]; 44 -> {45} [style=dotted]; - 45 -> {46} [style=dotted]; - 46 -> {47} [style=dotted]; + 44 -> {46} [color=green]; + 45 -> {47} [style=dotted]; + 46 -> {47} [color=green]; + 47 -> {50 48} [style=dotted]; + 48 -> {49} [style=dotted]; + 49 -> {50} [style=dotted]; } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.dot b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.dot index 67c971e8411..f9587a353ab 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.dot @@ -21,133 +21,128 @@ digraph inPlaceLambdas_kt { subgraph cluster_2 { color=red - 4 [label="Enter function run" style="filled" fillcolor=red]; - 5 [label="Function call: R|/block|.R|FakeOverride|()"]; - 6 [label="Exit function run" style="filled" fillcolor=red]; + 4 [label="Enter function test_1" style="filled" fillcolor=red]; + subgraph cluster_3 { + color=blue + 5 [label="Enter when"]; + subgraph cluster_4 { + color=blue + 6 [label="Enter when branch condition "]; + 7 [label="Access variable R|/x|"]; + 8 [label="Type operator: (R|/x| is R|A|)"]; + 9 [label="Exit when branch condition"]; + } + 10 [label="Synthetic else branch"]; + 11 [label="Enter when branch result"]; + subgraph cluster_5 { + color=blue + 12 [label="Enter block"]; + 13 [label="Postponed enter to lambda"]; + subgraph cluster_6 { + color=blue + 14 [label="Enter function anonymousFunction"]; + 15 [label="Access variable R|/x|"]; + 16 [label="Function call: R|/x|.R|/A.foo|()"]; + 17 [label="Exit function anonymousFunction"]; + } + 18 [label="Call arguments union" style="filled" fillcolor=yellow]; + 19 [label="Postponed exit from lambda"]; + 20 [label="Function call: R|kotlin/run|(...)"]; + 21 [label="Exit block"]; + } + 22 [label="Exit when branch result"]; + 23 [label="Exit when"]; + } + 24 [label="Exit function test_1" style="filled" fillcolor=red]; } 4 -> {5}; 5 -> {6}; - - subgraph cluster_3 { - color=red - 7 [label="Enter function test_1" style="filled" fillcolor=red]; - subgraph cluster_4 { - color=blue - 8 [label="Enter when"]; - subgraph cluster_5 { - color=blue - 9 [label="Enter when branch condition "]; - 10 [label="Access variable R|/x|"]; - 11 [label="Type operator: (R|/x| is R|A|)"]; - 12 [label="Exit when branch condition"]; - } - 13 [label="Synthetic else branch"]; - 14 [label="Enter when branch result"]; - subgraph cluster_6 { - color=blue - 15 [label="Enter block"]; - 16 [label="Postponed enter to lambda"]; - subgraph cluster_7 { - color=blue - 17 [label="Enter function anonymousFunction"]; - 18 [label="Access variable R|/x|"]; - 19 [label="Function call: R|/x|.R|/A.foo|()"]; - 20 [label="Exit function anonymousFunction"]; - } - 21 [label="Postponed exit from lambda"]; - 22 [label="Function call: R|/run|(...)"]; - 23 [label="Exit block"]; - } - 24 [label="Exit when branch result"]; - 25 [label="Exit when"]; - } - 26 [label="Exit function test_1" style="filled" fillcolor=red]; - } - + 6 -> {7}; 7 -> {8}; 8 -> {9}; - 9 -> {10}; - 10 -> {11}; + 9 -> {11 10}; + 10 -> {23}; 11 -> {12}; - 12 -> {14 13}; - 13 -> {25}; + 12 -> {13}; + 13 -> {14}; + 13 -> {19} [color=red]; 14 -> {15}; 15 -> {16}; 16 -> {17}; - 16 -> {21} [color=red]; - 17 -> {20 18}; - 18 -> {19}; - 19 -> {20}; - 20 -> {17}; - 20 -> {21} [color=green]; + 17 -> {19} [color=green]; + 17 -> {18} [color=red]; + 18 -> {20} [color=red]; + 19 -> {20} [color=green]; + 20 -> {21}; 21 -> {22}; 22 -> {23}; 23 -> {24}; - 24 -> {25}; - 25 -> {26}; - subgraph cluster_8 { + subgraph cluster_7 { color=red - 27 [label="Enter function test_2" style="filled" fillcolor=red]; - 28 [label="Postponed enter to lambda"]; - subgraph cluster_9 { + 25 [label="Enter function test_2" style="filled" fillcolor=red]; + 26 [label="Postponed enter to lambda"]; + subgraph cluster_8 { color=blue - 29 [label="Enter function anonymousFunction"]; - 30 [label="Access variable R|/x|"]; - 31 [label="Type operator: (R|/x| as R|B|)"]; - 32 [label="Exit function anonymousFunction"]; + 27 [label="Enter function anonymousFunction"]; + 28 [label="Access variable R|/x|"]; + 29 [label="Type operator: (R|/x| as R|B|)"]; + 30 [label="Exit function anonymousFunction"]; } - 33 [label="Postponed exit from lambda"]; - 34 [label="Function call: R|/run|(...)"]; - 35 [label="Access variable R|/x|"]; - 36 [label="Function call: R|/x|.R|/B.bar|()"]; - 37 [label="Exit function test_2" style="filled" fillcolor=red]; + 31 [label="Call arguments union" style="filled" fillcolor=yellow]; + 32 [label="Postponed exit from lambda"]; + 33 [label="Function call: R|kotlin/run|(...)"]; + 34 [label="Access variable R|/x|"]; + 35 [label="Function call: R|/x|.R|/B.bar|()"]; + 36 [label="Exit function test_2" style="filled" fillcolor=red]; } + 25 -> {26}; + 26 -> {27}; + 26 -> {32} [color=red]; 27 -> {28}; 28 -> {29}; - 28 -> {33} [color=red]; - 29 -> {32 30}; - 30 -> {31}; - 31 -> {32}; - 32 -> {29}; + 29 -> {30}; + 30 -> {32} [color=green]; + 30 -> {31} [color=red]; + 31 -> {33} [color=red]; 32 -> {33} [color=green]; 33 -> {34}; 34 -> {35}; 35 -> {36}; - 36 -> {37}; - subgraph cluster_10 { + subgraph cluster_9 { color=red - 38 [label="Enter function test_3" style="filled" fillcolor=red]; - subgraph cluster_11 { + 37 [label="Enter function test_3" style="filled" fillcolor=red]; + subgraph cluster_10 { color=blue - 39 [label="Enter when"]; + 38 [label="Enter when"]; + subgraph cluster_11 { + color=blue + 39 [label="Enter when branch condition "]; + 40 [label="Access variable R|/x|"]; + 41 [label="Type operator: (R|/x| is R|A|)"]; + 42 [label="Exit when branch condition"]; + } + 43 [label="Synthetic else branch"]; + 44 [label="Enter when branch result"]; subgraph cluster_12 { color=blue - 40 [label="Enter when branch condition "]; - 41 [label="Access variable R|/x|"]; - 42 [label="Type operator: (R|/x| is R|A|)"]; - 43 [label="Exit when branch condition"]; - } - 44 [label="Synthetic else branch"]; - 45 [label="Enter when branch result"]; - subgraph cluster_13 { - color=blue - 46 [label="Enter block"]; - 47 [label="Postponed enter to lambda"]; - subgraph cluster_14 { + 45 [label="Enter block"]; + 46 [label="Postponed enter to lambda"]; + subgraph cluster_13 { color=blue - 48 [label="Enter function anonymousFunction"]; - 49 [label="Access variable R|/x|"]; - 50 [label="Function call: R|/x|.R|/A.foo|()"]; - 51 [label="Access variable R|/x|"]; - 52 [label="Type operator: (R|/x| as R|B|)"]; - 53 [label="Exit function anonymousFunction"]; + 47 [label="Enter function anonymousFunction"]; + 48 [label="Access variable R|/x|"]; + 49 [label="Function call: R|/x|.R|/A.foo|()"]; + 50 [label="Access variable R|/x|"]; + 51 [label="Type operator: (R|/x| as R|B|)"]; + 52 [label="Exit function anonymousFunction"]; } + 53 [label="Call arguments union" style="filled" fillcolor=yellow]; 54 [label="Postponed exit from lambda"]; - 55 [label="Function call: R|/run|(...)"]; + 55 [label="Function call: R|kotlin/run|(...)"]; 56 [label="Access variable R|/x|"]; 57 [label="Function call: R|/x|.R|/B.bar|()"]; 58 [label="Exit block"]; @@ -158,25 +153,26 @@ digraph inPlaceLambdas_kt { 61 [label="Exit function test_3" style="filled" fillcolor=red]; } + 37 -> {38}; 38 -> {39}; 39 -> {40}; 40 -> {41}; 41 -> {42}; - 42 -> {43}; - 43 -> {45 44}; - 44 -> {60}; + 42 -> {44 43}; + 43 -> {60}; + 44 -> {45}; 45 -> {46}; 46 -> {47}; + 46 -> {54} [color=red]; 47 -> {48}; - 47 -> {54} [color=red]; - 48 -> {53 49}; + 48 -> {49}; 49 -> {50}; 50 -> {51}; 51 -> {52}; - 52 -> {53}; - 53 -> {48}; - 53 -> {54} [color=green]; - 54 -> {55}; + 52 -> {54} [color=green]; + 52 -> {53} [color=red]; + 53 -> {55} [color=red]; + 54 -> {55} [color=green]; 55 -> {56}; 56 -> {57}; 57 -> {58}; diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.kt b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.kt index 814a05ded5e..311e0c240e4 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.kt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.kt @@ -7,11 +7,6 @@ interface B { fun bar() } - -inline fun run(block: () -> Unit) { - block() -} - fun test_1(x: Any?) { if (x is A) { run { diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.txt b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.txt index 473f04676e9..16f58ddcc85 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.txt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/lambdas/inPlaceLambdas.txt @@ -7,13 +7,10 @@ FILE: inPlaceLambdas.kt public abstract fun bar(): R|kotlin/Unit| } - public final inline fun run(block: R|() -> kotlin/Unit|): R|kotlin/Unit| { - R|/block|.R|FakeOverride|() - } public final fun test_1(x: R|kotlin/Any?|): R|kotlin/Unit| { when () { (R|/x| is R|A|) -> { - R|/run|( = run@fun (): R|kotlin/Unit| { + R|kotlin/run|( = run@fun (): R|kotlin/Unit| { R|/x|.R|/A.foo|() } ) @@ -22,7 +19,7 @@ FILE: inPlaceLambdas.kt } public final fun test_2(x: R|kotlin/Any?|): R|kotlin/Unit| { - R|/run|( = run@fun (): R|kotlin/Unit| { + R|kotlin/run|( = run@fun (): R|B| { ^ (R|/x| as R|B|) } ) @@ -31,7 +28,7 @@ FILE: inPlaceLambdas.kt public final fun test_3(x: R|kotlin/Any?|): R|kotlin/Unit| { when () { (R|/x| is R|A|) -> { - R|/run|( = run@fun (): R|kotlin/Unit| { + R|kotlin/run|( = run@fun (): R|B| { R|/x|.R|/A.foo|() ^ (R|/x| as R|B|) } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.dot b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.dot index e6d923cd203..b99eaff8f73 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/receivers/implicitReceivers.dot @@ -214,163 +214,169 @@ digraph implicitReceivers_kt { 78 [label="Function call: this@R|special/anonymous|.R|/A.foo|()"]; 79 [label="Exit function anonymousFunction"]; } - 80 [label="Postponed exit from lambda"]; - 81 [label="Function call: R|kotlin/with|(...)"]; - 82 [label="Access variable this@R|special/anonymous|"]; - 83 [label="Function call: this@R|special/anonymous|.R|/A.foo|()"]; + 80 [label="Call arguments union" style="filled" fillcolor=yellow]; + 81 [label="Postponed exit from lambda"]; + 82 [label="Function call: R|kotlin/with|(...)"]; + 83 [label="Access variable this@R|special/anonymous|"]; 84 [label="Function call: this@R|special/anonymous|.R|/A.foo|()"]; - 85 [label="Exit function anonymousFunction"]; + 85 [label="Function call: this@R|special/anonymous|.R|/A.foo|()"]; + 86 [label="Exit function anonymousFunction"]; } - 86 [label="Postponed exit from lambda"]; - 87 [label="Function call: R|kotlin/with|(...)"]; - 88 [label="Exit function anonymousFunction"]; + 87 [label="Call arguments union" style="filled" fillcolor=yellow]; + 88 [label="Postponed exit from lambda"]; + 89 [label="Function call: R|kotlin/with|(...)"]; + 90 [label="Exit function anonymousFunction"]; } - 89 [label="Postponed exit from lambda"]; - 90 [label="Function call: R|kotlin/with|(...)"]; - 91 [label="Exit function test_3" style="filled" fillcolor=red]; + 91 [label="Call arguments union" style="filled" fillcolor=yellow]; + 92 [label="Postponed exit from lambda"]; + 93 [label="Function call: R|kotlin/with|(...)"]; + 94 [label="Exit function test_3" style="filled" fillcolor=red]; } 64 -> {65}; 65 -> {66}; 66 -> {67}; - 66 -> {89} [color=red]; + 66 -> {92} [color=red]; 67 -> {68}; 68 -> {69}; 69 -> {70}; - 69 -> {86} [color=red]; + 69 -> {88} [color=red]; 70 -> {71}; 71 -> {72}; 72 -> {73}; - 72 -> {80} [color=red]; + 72 -> {81} [color=red]; 73 -> {74}; 74 -> {75}; 75 -> {76}; 76 -> {77}; 77 -> {78}; 78 -> {79}; - 79 -> {80} [color=green]; - 80 -> {81}; - 81 -> {82}; + 79 -> {81} [color=green]; + 79 -> {80} [color=red]; + 80 -> {82} [color=red]; + 81 -> {82} [color=green]; 82 -> {83}; 83 -> {84}; 84 -> {85}; - 85 -> {86} [color=green]; - 86 -> {87}; - 87 -> {88}; + 85 -> {86}; + 86 -> {88} [color=green]; + 86 -> {87} [color=red]; + 87 -> {89} [color=red]; 88 -> {89} [color=green]; 89 -> {90}; - 90 -> {91}; + 90 -> {92} [color=green]; + 90 -> {91} [color=red]; + 91 -> {93} [color=red]; + 92 -> {93} [color=green]; + 93 -> {94}; subgraph cluster_21 { color=red - 92 [label="Enter function test_4" style="filled" fillcolor=red]; + 95 [label="Enter function test_4" style="filled" fillcolor=red]; subgraph cluster_22 { color=blue - 93 [label="Enter when"]; + 96 [label="Enter when"]; subgraph cluster_23 { color=blue - 94 [label="Enter when branch condition "]; - 95 [label="Access variable this@R|/test_4|"]; - 96 [label="Type operator: (this@R|/test_4| !is R|A|)"]; - 97 [label="Exit when branch condition"]; + 97 [label="Enter when branch condition "]; + 98 [label="Access variable this@R|/test_4|"]; + 99 [label="Type operator: (this@R|/test_4| !is R|A|)"]; + 100 [label="Exit when branch condition"]; } subgraph cluster_24 { color=blue - 98 [label="Enter when branch condition else"]; - 99 [label="Exit when branch condition"]; + 101 [label="Enter when branch condition else"]; + 102 [label="Exit when branch condition"]; } - 100 [label="Enter when branch result"]; + 103 [label="Enter when branch result"]; subgraph cluster_25 { color=blue - 101 [label="Enter block"]; + 104 [label="Enter block"]; subgraph cluster_26 { color=blue - 102 [label="Enter when"]; + 105 [label="Enter when"]; subgraph cluster_27 { color=blue - 103 [label="Enter when branch condition "]; - 104 [label="Access variable this@R|/test_4|"]; - 105 [label="Type operator: (this@R|/test_4| !is R|B|)"]; - 106 [label="Exit when branch condition"]; + 106 [label="Enter when branch condition "]; + 107 [label="Access variable this@R|/test_4|"]; + 108 [label="Type operator: (this@R|/test_4| !is R|B|)"]; + 109 [label="Exit when branch condition"]; } subgraph cluster_28 { color=blue - 107 [label="Enter when branch condition else"]; - 108 [label="Exit when branch condition"]; + 110 [label="Enter when branch condition else"]; + 111 [label="Exit when branch condition"]; } - 109 [label="Enter when branch result"]; + 112 [label="Enter when branch result"]; subgraph cluster_29 { color=blue - 110 [label="Enter block"]; - 111 [label="Access variable this@R|/test_4|"]; - 112 [label="Function call: this@R|/test_4|.R|/A.foo|()"]; - 113 [label="Function call: this@R|/test_4|.R|/A.foo|()"]; + 113 [label="Enter block"]; 114 [label="Access variable this@R|/test_4|"]; - 115 [label="Function call: this@R|/test_4|.R|/B.bar|()"]; - 116 [label="Function call: this@R|/test_4|.R|/B.bar|()"]; - 117 [label="Exit block"]; + 115 [label="Function call: this@R|/test_4|.R|/A.foo|()"]; + 116 [label="Function call: this@R|/test_4|.R|/A.foo|()"]; + 117 [label="Access variable this@R|/test_4|"]; + 118 [label="Function call: this@R|/test_4|.R|/B.bar|()"]; + 119 [label="Function call: this@R|/test_4|.R|/B.bar|()"]; + 120 [label="Exit block"]; } - 118 [label="Exit when branch result"]; - 119 [label="Enter when branch result"]; + 121 [label="Exit when branch result"]; + 122 [label="Enter when branch result"]; subgraph cluster_30 { color=blue - 120 [label="Enter block"]; - 121 [label="Access variable this@R|/test_4|"]; - 122 [label="Function call: this@R|/test_4|.#()"]; - 123 [label="Function call: #()"]; + 123 [label="Enter block"]; 124 [label="Access variable this@R|/test_4|"]; - 125 [label="Function call: this@R|/test_4|.R|/A.foo|()"]; - 126 [label="Function call: this@R|/test_4|.R|/A.foo|()"]; - 127 [label="Exit block"]; + 125 [label="Function call: this@R|/test_4|.#()"]; + 126 [label="Function call: #()"]; + 127 [label="Access variable this@R|/test_4|"]; + 128 [label="Function call: this@R|/test_4|.R|/A.foo|()"]; + 129 [label="Function call: this@R|/test_4|.R|/A.foo|()"]; + 130 [label="Exit block"]; } - 128 [label="Exit when branch result"]; - 129 [label="Exit when"]; + 131 [label="Exit when branch result"]; + 132 [label="Exit when"]; } - 130 [label="Exit block"]; + 133 [label="Exit block"]; } - 131 [label="Exit when branch result"]; - 132 [label="Enter when branch result"]; + 134 [label="Exit when branch result"]; + 135 [label="Enter when branch result"]; subgraph cluster_31 { color=blue - 133 [label="Enter block"]; - 134 [label="Access variable this@R|/test_4|"]; - 135 [label="Function call: this@R|/test_4|.#()"]; - 136 [label="Function call: #()"]; + 136 [label="Enter block"]; 137 [label="Access variable this@R|/test_4|"]; - 138 [label="Function call: this@R|/test_4|.#()"]; - 139 [label="Function call: #()"]; - 140 [label="Exit block"]; + 138 [label="Function call: this@R|/test_4|.#()"]; + 139 [label="Function call: #()"]; + 140 [label="Access variable this@R|/test_4|"]; + 141 [label="Function call: this@R|/test_4|.#()"]; + 142 [label="Function call: #()"]; + 143 [label="Exit block"]; } - 141 [label="Exit when branch result"]; - 142 [label="Exit when"]; + 144 [label="Exit when branch result"]; + 145 [label="Exit when"]; } - 143 [label="Access variable this@R|/test_4|"]; - 144 [label="Function call: this@R|/test_4|.#()"]; - 145 [label="Function call: #()"]; 146 [label="Access variable this@R|/test_4|"]; - 147 [label="Function call: this@R|/test_4|.#()"]; - 148 [label="Function call: #()"]; - 149 [label="Exit function test_4" style="filled" fillcolor=red]; + 147 [label="Function call: this@R|/test_4|.#()"]; + 148 [label="Function call: #()"]; + 149 [label="Access variable this@R|/test_4|"]; + 150 [label="Function call: this@R|/test_4|.#()"]; + 151 [label="Function call: #()"]; + 152 [label="Exit function test_4" style="filled" fillcolor=red]; } - 92 -> {93}; - 93 -> {94}; - 94 -> {95}; 95 -> {96}; 96 -> {97}; - 97 -> {132 98}; + 97 -> {98}; 98 -> {99}; 99 -> {100}; - 100 -> {101}; + 100 -> {135 101}; 101 -> {102}; 102 -> {103}; 103 -> {104}; 104 -> {105}; 105 -> {106}; - 106 -> {119 107}; + 106 -> {107}; 107 -> {108}; 108 -> {109}; - 109 -> {110}; + 109 -> {122 110}; 110 -> {111}; 111 -> {112}; 112 -> {113}; @@ -379,10 +385,10 @@ digraph implicitReceivers_kt { 115 -> {116}; 116 -> {117}; 117 -> {118}; - 118 -> {129}; + 118 -> {119}; 119 -> {120}; 120 -> {121}; - 121 -> {122}; + 121 -> {132}; 122 -> {123}; 123 -> {124}; 124 -> {125}; @@ -392,10 +398,10 @@ digraph implicitReceivers_kt { 128 -> {129}; 129 -> {130}; 130 -> {131}; - 131 -> {142}; + 131 -> {132}; 132 -> {133}; 133 -> {134}; - 134 -> {135}; + 134 -> {145}; 135 -> {136}; 136 -> {137}; 137 -> {138}; @@ -410,59 +416,62 @@ digraph implicitReceivers_kt { 146 -> {147}; 147 -> {148}; 148 -> {149}; + 149 -> {150}; + 150 -> {151}; + 151 -> {152}; subgraph cluster_32 { color=red - 150 [label="Enter function test_5" style="filled" fillcolor=red]; + 153 [label="Enter function test_5" style="filled" fillcolor=red]; subgraph cluster_33 { color=blue - 151 [label="Enter when"]; + 154 [label="Enter when"]; subgraph cluster_34 { color=blue - 152 [label="Enter when branch condition "]; - 153 [label="Access variable this@R|/test_5|"]; - 154 [label="Type operator: (this@R|/test_5| is R|kotlin/collections/List<*>|)"]; - 155 [label="Exit when branch condition"]; + 155 [label="Enter when branch condition "]; + 156 [label="Access variable this@R|/test_5|"]; + 157 [label="Type operator: (this@R|/test_5| is R|kotlin/collections/List<*>|)"]; + 158 [label="Exit when branch condition"]; } subgraph cluster_35 { color=blue - 156 [label="Enter when branch condition "]; - 157 [label="Access variable this@R|/test_5|"]; - 158 [label="Type operator: (this@R|/test_5| is R|kotlin/String|)"]; - 159 [label="Exit when branch condition"]; + 159 [label="Enter when branch condition "]; + 160 [label="Access variable this@R|/test_5|"]; + 161 [label="Type operator: (this@R|/test_5| is R|kotlin/String|)"]; + 162 [label="Exit when branch condition"]; } subgraph cluster_36 { color=blue - 160 [label="Enter when branch condition else"]; - 161 [label="Exit when branch condition"]; + 163 [label="Enter when branch condition else"]; + 164 [label="Exit when branch condition"]; } - 162 [label="Enter when branch result"]; + 165 [label="Enter when branch result"]; subgraph cluster_37 { color=blue - 163 [label="Enter block"]; - 164 [label="Const: Int(0)"]; - 165 [label="Exit block"]; + 166 [label="Enter block"]; + 167 [label="Const: Int(0)"]; + 168 [label="Exit block"]; } - 166 [label="Exit when branch result"]; - 167 [label="Enter when branch result"]; + 169 [label="Exit when branch result"]; + 170 [label="Enter when branch result"]; subgraph cluster_38 { color=blue - 168 [label="Enter block"]; - 169 [label="Access variable R|kotlin/String.length|"]; - 170 [label="Exit block"]; + 171 [label="Enter block"]; + 172 [label="Access variable R|kotlin/String.length|"]; + 173 [label="Exit block"]; } - 171 [label="Exit when branch result"]; - 172 [label="Enter when branch result"]; + 174 [label="Exit when branch result"]; + 175 [label="Enter when branch result"]; subgraph cluster_39 { color=blue - 173 [label="Enter block"]; - 174 [label="Access variable R|kotlin/collections/List.size|"]; - 175 [label="Exit block"]; + 176 [label="Enter block"]; + 177 [label="Access variable R|kotlin/collections/List.size|"]; + 178 [label="Exit block"]; } - 176 [label="Exit when branch result"]; - 177 [label="Exit when"]; + 179 [label="Exit when branch result"]; + 180 [label="Exit when"]; } - 178 [label="Jump: ^test_5 when () { + 181 [label="Jump: ^test_5 when () { (this@R|/test_5| is R|kotlin/collections/List<*>|) -> { this@R|/test_5|.R|kotlin/collections/List.size| } @@ -474,60 +483,60 @@ digraph implicitReceivers_kt { } } "]; - 179 [label="Stub" style="filled" fillcolor=gray]; - 180 [label="Exit function test_5" style="filled" fillcolor=red]; + 182 [label="Stub" style="filled" fillcolor=gray]; + 183 [label="Exit function test_5" style="filled" fillcolor=red]; } - 150 -> {151}; - 151 -> {152}; - 152 -> {153}; 153 -> {154}; 154 -> {155}; - 155 -> {172 156}; + 155 -> {156}; 156 -> {157}; 157 -> {158}; - 158 -> {159}; - 159 -> {167 160}; + 158 -> {175 159}; + 159 -> {160}; 160 -> {161}; 161 -> {162}; - 162 -> {163}; + 162 -> {170 163}; 163 -> {164}; 164 -> {165}; 165 -> {166}; - 166 -> {177}; + 166 -> {167}; 167 -> {168}; 168 -> {169}; - 169 -> {170}; + 169 -> {180}; 170 -> {171}; - 171 -> {177}; + 171 -> {172}; 172 -> {173}; 173 -> {174}; - 174 -> {175}; + 174 -> {180}; 175 -> {176}; 176 -> {177}; 177 -> {178}; - 178 -> {180}; - 178 -> {179} [style=dotted]; - 179 -> {180} [style=dotted]; + 178 -> {179}; + 179 -> {180}; + 180 -> {181}; + 181 -> {183}; + 181 -> {182} [style=dotted]; + 182 -> {183} [style=dotted]; subgraph cluster_40 { color=red - 181 [label="Enter function test_6" style="filled" fillcolor=red]; - 182 [label="Access variable this@R|/test_6|"]; - 183 [label="Type operator: (this@R|/test_6| as R|kotlin/collections/List<*>|)"]; - 184 [label="Access variable R|kotlin/collections/List.size|"]; + 184 [label="Enter function test_6" style="filled" fillcolor=red]; 185 [label="Access variable this@R|/test_6|"]; - 186 [label="Type operator: (this@R|/test_6| as R|kotlin/String|)"]; - 187 [label="Access variable R|kotlin/String.length|"]; - 188 [label="Exit function test_6" style="filled" fillcolor=red]; + 186 [label="Type operator: (this@R|/test_6| as R|kotlin/collections/List<*>|)"]; + 187 [label="Access variable R|kotlin/collections/List.size|"]; + 188 [label="Access variable this@R|/test_6|"]; + 189 [label="Type operator: (this@R|/test_6| as R|kotlin/String|)"]; + 190 [label="Access variable R|kotlin/String.length|"]; + 191 [label="Exit function test_6" style="filled" fillcolor=red]; } - 181 -> {182}; - 182 -> {183}; - 183 -> {184}; 184 -> {185}; 185 -> {186}; 186 -> {187}; 187 -> {188}; + 188 -> {189}; + 189 -> {190}; + 190 -> {191}; } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.dot b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.dot index 02e7a98a1c5..d90a9af6ead 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/safeCalls/safeCalls.dot @@ -201,38 +201,41 @@ digraph safeCalls_kt { 76 [label="Stub" style="filled" fillcolor=gray]; 77 [label="Exit function anonymousFunction" style="filled" fillcolor=gray]; } - 78 [label="Postponed exit from lambda"]; - 79 [label="Function call: R|/x|?.R|kotlin/let|(...)"]; - 80 [label="Exit safe call"]; - 81 [label="Enter safe call"]; - 82 [label="Access variable R|/x|"]; - 83 [label="Function call: R|/x|.R|/A.bool|()"]; - 84 [label="Function call: R|/x|?.R|kotlin/let|(...)?.R|/boo|(...)"]; - 85 [label="Exit safe call"]; - 86 [label="Access variable R|/x|"]; - 87 [label="Function call: R|/x|.#()"]; - 88 [label="Exit function test_5" style="filled" fillcolor=red]; + 78 [label="Call arguments union" style="filled" fillcolor=gray]; + 79 [label="Postponed exit from lambda"]; + 80 [label="Function call: R|/x|?.R|kotlin/let|(...)" style="filled" fillcolor=gray]; + 81 [label="Exit safe call"]; + 82 [label="Enter safe call"]; + 83 [label="Access variable R|/x|"]; + 84 [label="Function call: R|/x|.R|/A.bool|()"]; + 85 [label="Function call: R|/x|?.R|kotlin/let|(...)?.R|/boo|(...)"]; + 86 [label="Exit safe call"]; + 87 [label="Access variable R|/x|"]; + 88 [label="Function call: R|/x|.#()"]; + 89 [label="Exit function test_5" style="filled" fillcolor=red]; } 70 -> {71}; - 71 -> {72 80}; + 71 -> {72 81}; 72 -> {73}; 73 -> {74}; - 73 -> {78} [color=red]; + 73 -> {79} [color=red]; 74 -> {75}; - 75 -> {88}; + 75 -> {89}; 75 -> {76} [style=dotted]; 76 -> {77} [style=dotted]; - 77 -> {78} [color=green]; - 78 -> {79}; - 79 -> {80}; - 80 -> {81 85}; - 81 -> {82}; + 77 -> {78} [style=dotted]; + 77 -> {79} [color=green]; + 78 -> {80} [style=dotted]; + 79 -> {80} [color=green]; + 80 -> {81} [style=dotted]; + 81 -> {82 86}; 82 -> {83}; 83 -> {84}; 84 -> {85}; 85 -> {86}; 86 -> {87}; 87 -> {88}; + 88 -> {89}; } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastToNothing.dot b/compiler/fir/resolve/testData/resolve/smartcasts/smartcastToNothing.dot index a755a2823d1..5496468a8bc 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/smartcastToNothing.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/smartcastToNothing.dot @@ -214,10 +214,11 @@ digraph smartcastToNothing_kt { 86 [label="Access variable R|/A.a|"]; 87 [label="Exit function anonymousFunction"]; } - 88 [label="Postponed exit from lambda"]; - 89 [label="Function call: R|/s|?.R|kotlin/let|(...)"]; - 90 [label="Exit safe call"]; - 91 [label="Exit function test_0" style="filled" fillcolor=red]; + 88 [label="Call arguments union" style="filled" fillcolor=yellow]; + 89 [label="Postponed exit from lambda"]; + 90 [label="Function call: R|/s|?.R|kotlin/let|(...)"]; + 91 [label="Exit safe call"]; + 92 [label="Exit function test_0" style="filled" fillcolor=red]; } 44 -> {45}; @@ -234,16 +235,16 @@ digraph smartcastToNothing_kt { 55 -> {56}; 56 -> {57}; 57 -> {58}; - 58 -> {91}; + 58 -> {92}; 58 -> {59} [style=dotted]; 59 -> {60} [style=dotted]; 60 -> {61} [style=dotted]; - 61 -> {91 62} [style=dotted]; + 61 -> {92 62} [style=dotted]; 62 -> {63} [style=dotted]; 63 -> {64} [style=dotted]; 64 -> {65} [style=dotted]; 65 -> {66} [style=dotted]; - 66 -> {91 67} [style=dotted]; + 66 -> {92 67} [style=dotted]; 67 -> {68} [style=dotted]; 68 -> {69} [style=dotted]; 69 -> {71 70} [style=dotted]; @@ -258,16 +259,18 @@ digraph smartcastToNothing_kt { 78 -> {79} [style=dotted]; 79 -> {51} [style=dotted]; 80 -> {81}; - 81 -> {82 90}; + 81 -> {82 91}; 82 -> {83}; 83 -> {84}; - 83 -> {88} [color=red]; + 83 -> {89} [color=red]; 84 -> {85}; 85 -> {86}; 86 -> {87}; - 87 -> {88} [color=green]; - 88 -> {89}; - 89 -> {90}; - 90 -> {91} [style=dotted]; + 87 -> {89} [color=green]; + 87 -> {88} [color=red]; + 88 -> {90} [color=red]; + 89 -> {90} [color=green]; + 90 -> {91}; + 91 -> {92} [style=dotted]; } diff --git a/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.dot b/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.dot index 0d6159febd0..d0120f9eb2f 100644 --- a/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.dot +++ b/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.dot @@ -15,272 +15,281 @@ digraph callsInPlace_kt { 5 [label="Assignmenet: R|/x|"]; 6 [label="Exit function anonymousFunction"]; } - 7 [label="Postponed exit from lambda"]; - 8 [label="Function call: R|kotlin/run|(...)"]; - 9 [label="Access variable R|/x|"]; - 10 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; - 11 [label="Exit function test" style="filled" fillcolor=red]; + 7 [label="Call arguments union" style="filled" fillcolor=yellow]; + 8 [label="Postponed exit from lambda"]; + 9 [label="Function call: R|kotlin/run|(...)"]; + 10 [label="Access variable R|/x|"]; + 11 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 12 [label="Exit function test" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; - 2 -> {7} [color=red]; + 2 -> {8} [color=red]; 3 -> {4}; 4 -> {5}; 5 -> {6}; - 6 -> {7} [color=green]; - 7 -> {8}; - 8 -> {9}; + 6 -> {8} [color=green]; + 6 -> {7} [color=red]; + 7 -> {9} [color=red]; + 8 -> {9} [color=green]; 9 -> {10}; 10 -> {11}; + 11 -> {12}; subgraph cluster_2 { color=red - 12 [label="Enter function test_2" style="filled" fillcolor=red]; - 13 [label="Const: Int(10)"]; - 14 [label="Postponed enter to lambda"]; + 13 [label="Enter function test_2" style="filled" fillcolor=red]; + 14 [label="Const: Int(10)"]; + 15 [label="Postponed enter to lambda"]; subgraph cluster_3 { color=blue - 15 [label="Enter function anonymousFunction"]; - 16 [label="Const: String(test_2)"]; - 17 [label="Exit function anonymousFunction"]; + 16 [label="Enter function anonymousFunction"]; + 17 [label="Const: String(test_2)"]; + 18 [label="Exit function anonymousFunction"]; } - 18 [label="Postponed exit from lambda"]; - 19 [label="Function call: R|kotlin/repeat|(...)"]; - 20 [label="Exit function test_2" style="filled" fillcolor=red]; + 19 [label="Postponed exit from lambda"]; + 20 [label="Function call: R|kotlin/repeat|(...)"]; + 21 [label="Exit function test_2" style="filled" fillcolor=red]; } - 12 -> {13}; 13 -> {14}; 14 -> {15}; - 14 -> {18} [color=red]; - 15 -> {17 16}; - 16 -> {17}; - 17 -> {15}; - 17 -> {18} [color=green]; - 18 -> {19}; + 15 -> {16}; + 15 -> {19} [color=red]; + 16 -> {18 17}; + 17 -> {18}; + 18 -> {16}; + 18 -> {19} [color=green]; 19 -> {20}; + 20 -> {21}; subgraph cluster_4 { color=red - 21 [label="Enter function test_3" style="filled" fillcolor=red]; - 22 [label="Postponed enter to lambda"]; + 22 [label="Enter function test_3" style="filled" fillcolor=red]; + 23 [label="Postponed enter to lambda"]; subgraph cluster_5 { color=blue - 23 [label="Enter function anonymousFunction"]; - 24 [label="Const: String(test_3)"]; - 25 [label="Exit function anonymousFunction"]; + 24 [label="Enter function anonymousFunction"]; + 25 [label="Const: String(test_3)"]; + 26 [label="Exit function anonymousFunction"]; } - 26 [label="Postponed exit from lambda"]; - 27 [label="Const: Int(10)"]; - 28 [label="Function call: R|kotlin/repeat|(...)"]; - 29 [label="Exit function test_3" style="filled" fillcolor=red]; + 27 [label="Postponed exit from lambda"]; + 28 [label="Const: Int(10)"]; + 29 [label="Function call: R|kotlin/repeat|(...)"]; + 30 [label="Exit function test_3" style="filled" fillcolor=red]; } - 21 -> {22}; 22 -> {23}; - 22 -> {26} [color=red]; - 23 -> {25 24}; - 24 -> {25}; - 25 -> {23}; - 25 -> {26} [color=green]; - 26 -> {27}; + 23 -> {24}; + 23 -> {27} [color=red]; + 24 -> {26 25}; + 25 -> {26}; + 26 -> {24}; + 26 -> {27} [color=green]; 27 -> {28}; 28 -> {29}; + 29 -> {30}; subgraph cluster_6 { color=red - 30 [label="Enter function test_4" style="filled" fillcolor=red]; - 31 [label="Const: Int(1)"]; - 32 [label="Postponed enter to lambda"]; + 31 [label="Enter function test_4" style="filled" fillcolor=red]; + 32 [label="Const: Int(1)"]; + 33 [label="Postponed enter to lambda"]; subgraph cluster_7 { color=blue - 33 [label="Enter function anonymousFunction"]; - 34 [label="Const: String(test_4)"]; - 35 [label="Access variable R|/it|"]; - 36 [label="Const: Int(0)"]; - 37 [label="Function call: R|/it|.R|kotlin/Int.compareTo|(...)"]; - 38 [label="Comparison >"]; - 39 [label="Exit function anonymousFunction"]; + 34 [label="Enter function anonymousFunction"]; + 35 [label="Const: String(test_4)"]; + 36 [label="Access variable R|/it|"]; + 37 [label="Const: Int(0)"]; + 38 [label="Function call: R|/it|.R|kotlin/Int.compareTo|(...)"]; + 39 [label="Comparison >"]; + 40 [label="Exit function anonymousFunction"]; } - 40 [label="Postponed exit from lambda"]; - 41 [label="Function call: Int(1).R|kotlin/takeUnless|(...)"]; - 42 [label="Exit function test_4" style="filled" fillcolor=red]; + 41 [label="Call arguments union" style="filled" fillcolor=yellow]; + 42 [label="Postponed exit from lambda"]; + 43 [label="Function call: Int(1).R|kotlin/takeUnless|(...)"]; + 44 [label="Exit function test_4" style="filled" fillcolor=red]; } - 30 -> {31}; 31 -> {32}; 32 -> {33}; - 32 -> {40} [color=red]; 33 -> {34}; + 33 -> {42} [color=red]; 34 -> {35}; 35 -> {36}; 36 -> {37}; 37 -> {38}; 38 -> {39}; - 39 -> {40} [color=green]; - 40 -> {41}; - 41 -> {42}; + 39 -> {40}; + 40 -> {42} [color=green]; + 40 -> {41} [color=red]; + 41 -> {43} [color=red]; + 42 -> {43} [color=green]; + 43 -> {44}; subgraph cluster_8 { color=red - 43 [label="Enter function test_5" style="filled" fillcolor=red]; - 44 [label="Const: Int(1)"]; - 45 [label="Postponed enter to lambda"]; + 45 [label="Enter function test_5" style="filled" fillcolor=red]; + 46 [label="Const: Int(1)"]; + 47 [label="Postponed enter to lambda"]; subgraph cluster_9 { color=blue - 46 [label="Enter function anonymousFunction"]; - 47 [label="Const: String(test_5)"]; - 48 [label="Access variable R|/it|"]; - 49 [label="Const: Int(0)"]; - 50 [label="Function call: R|/it|.R|kotlin/Int.compareTo|(...)"]; - 51 [label="Comparison >"]; - 52 [label="Exit function anonymousFunction"]; + 48 [label="Enter function anonymousFunction"]; + 49 [label="Const: String(test_5)"]; + 50 [label="Access variable R|/it|"]; + 51 [label="Const: Int(0)"]; + 52 [label="Function call: R|/it|.R|kotlin/Int.compareTo|(...)"]; + 53 [label="Comparison >"]; + 54 [label="Exit function anonymousFunction"]; } - 53 [label="Postponed exit from lambda"]; - 54 [label="Function call: Int(1).R|kotlin/takeUnless|(...)"]; - 55 [label="Exit function test_5" style="filled" fillcolor=red]; + 55 [label="Call arguments union" style="filled" fillcolor=yellow]; + 56 [label="Postponed exit from lambda"]; + 57 [label="Function call: Int(1).R|kotlin/takeUnless|(...)"]; + 58 [label="Exit function test_5" style="filled" fillcolor=red]; } - 43 -> {44}; - 44 -> {45}; 45 -> {46}; - 45 -> {53} [color=red]; 46 -> {47}; 47 -> {48}; + 47 -> {56} [color=red]; 48 -> {49}; 49 -> {50}; 50 -> {51}; 51 -> {52}; - 52 -> {53} [color=green]; + 52 -> {53}; 53 -> {54}; - 54 -> {55}; + 54 -> {56} [color=green]; + 54 -> {55} [color=red]; + 55 -> {57} [color=red]; + 56 -> {57} [color=green]; + 57 -> {58}; subgraph cluster_10 { color=red - 56 [label="Enter function myRun" style="filled" fillcolor=red]; - 57 [label="Function call: R|/block1|.R|FakeOverride|()"]; - 58 [label="Function call: R|/block2|.R|FakeOverride|()"]; - 59 [label="Exit function myRun" style="filled" fillcolor=red]; + 59 [label="Enter function myRun" style="filled" fillcolor=red]; + 60 [label="Function call: R|/block1|.R|FakeOverride|()"]; + 61 [label="Function call: R|/block2|.R|FakeOverride|()"]; + 62 [label="Exit function myRun" style="filled" fillcolor=red]; } - 56 -> {57}; - 57 -> {58}; - 58 -> {59}; + 59 -> {60}; + 60 -> {61}; + 61 -> {62}; subgraph cluster_11 { color=red - 60 [label="Enter function test_6" style="filled" fillcolor=red]; - 61 [label="Postponed enter to lambda"]; + 63 [label="Enter function test_6" style="filled" fillcolor=red]; + 64 [label="Postponed enter to lambda"]; subgraph cluster_12 { color=blue - 62 [label="Enter function anonymousFunction"]; - 63 [label="Const: String(test_6_1)"]; - 64 [label="Exit function anonymousFunction"]; + 65 [label="Enter function anonymousFunction"]; + 66 [label="Const: String(test_6_1)"]; + 67 [label="Exit function anonymousFunction"]; } - 65 [label="Postponed exit from lambda"]; - 66 [label="Postponed enter to lambda"]; + 68 [label="Postponed exit from lambda"]; + 69 [label="Postponed enter to lambda"]; subgraph cluster_13 { color=blue - 67 [label="Enter function anonymousFunction"]; - 68 [label="Const: String(test_6_2)"]; - 69 [label="Exit function anonymousFunction"]; + 70 [label="Enter function anonymousFunction"]; + 71 [label="Const: String(test_6_2)"]; + 72 [label="Exit function anonymousFunction"]; } - 70 [label="Postponed exit from lambda"]; - 71 [label="Function call: R|/myRun|(...)"]; - 72 [label="Exit function test_6" style="filled" fillcolor=red]; + 73 [label="Postponed exit from lambda"]; + 74 [label="Function call: R|/myRun|(...)"]; + 75 [label="Exit function test_6" style="filled" fillcolor=red]; } - 60 -> {61}; - 61 -> {62}; - 61 -> {65} [color=red]; - 62 -> {64 63}; 63 -> {64}; - 64 -> {62}; - 64 -> {65} [color=green]; - 65 -> {66}; + 64 -> {65}; + 64 -> {68} [color=red]; + 65 -> {67 66}; 66 -> {67}; - 66 -> {70} [color=red]; - 67 -> {69 68}; + 67 -> {65}; + 67 -> {68} [color=green]; 68 -> {69}; - 69 -> {67}; - 69 -> {70} [color=green]; - 70 -> {71}; + 69 -> {70}; + 69 -> {73} [color=red]; + 70 -> {72 71}; 71 -> {72}; + 72 -> {70}; + 72 -> {73} [color=green]; + 73 -> {74}; + 74 -> {75}; subgraph cluster_14 { color=red - 73 [label="Enter function test_7" style="filled" fillcolor=red]; - 74 [label="Postponed enter to lambda"]; + 76 [label="Enter function test_7" style="filled" fillcolor=red]; + 77 [label="Postponed enter to lambda"]; subgraph cluster_15 { color=blue - 75 [label="Enter function anonymousFunction"]; - 76 [label="Const: String(test_7_2)"]; - 77 [label="Exit function anonymousFunction"]; + 78 [label="Enter function anonymousFunction"]; + 79 [label="Const: String(test_7_2)"]; + 80 [label="Exit function anonymousFunction"]; } - 78 [label="Postponed exit from lambda"]; - 79 [label="Postponed enter to lambda"]; + 81 [label="Postponed exit from lambda"]; + 82 [label="Postponed enter to lambda"]; subgraph cluster_16 { color=blue - 80 [label="Enter function anonymousFunction"]; - 81 [label="Const: String(test_7_1)"]; - 82 [label="Exit function anonymousFunction"]; + 83 [label="Enter function anonymousFunction"]; + 84 [label="Const: String(test_7_1)"]; + 85 [label="Exit function anonymousFunction"]; } - 83 [label="Postponed exit from lambda"]; - 84 [label="Function call: R|/myRun|(...)"]; - 85 [label="Exit function test_7" style="filled" fillcolor=red]; + 86 [label="Postponed exit from lambda"]; + 87 [label="Function call: R|/myRun|(...)"]; + 88 [label="Exit function test_7" style="filled" fillcolor=red]; } - 73 -> {74}; - 74 -> {75}; - 74 -> {78} [color=red]; - 75 -> {77 76}; 76 -> {77}; - 77 -> {75}; - 77 -> {78} [color=green]; - 78 -> {79}; + 77 -> {78}; + 77 -> {81} [color=red]; + 78 -> {80 79}; 79 -> {80}; - 79 -> {83} [color=red]; - 80 -> {82 81}; + 80 -> {78}; + 80 -> {81} [color=green]; 81 -> {82}; - 82 -> {80}; - 82 -> {83} [color=green]; - 83 -> {84}; + 82 -> {83}; + 82 -> {86} [color=red]; + 83 -> {85 84}; 84 -> {85}; - - subgraph cluster_17 { - color=red - 86 [label="Enter function myDummyRun" style="filled" fillcolor=red]; - 87 [label="Function call: R|/block|.R|FakeOverride|()"]; - 88 [label="Exit function myDummyRun" style="filled" fillcolor=red]; - } - + 85 -> {83}; + 85 -> {86} [color=green]; 86 -> {87}; 87 -> {88}; - subgraph cluster_18 { + subgraph cluster_17 { color=red - 89 [label="Enter function test_8" style="filled" fillcolor=red]; - 90 [label="Postponed enter to lambda"]; - 91 [label="Postponed exit from lambda"]; - 92 [label="Function call: R|/myDummyRun|(...)"]; - 93 [label="Exit function test_8" style="filled" fillcolor=red]; + 89 [label="Enter function myDummyRun" style="filled" fillcolor=red]; + 90 [label="Function call: R|/block|.R|FakeOverride|()"]; + 91 [label="Exit function myDummyRun" style="filled" fillcolor=red]; } 89 -> {90}; - 90 -> {91 91} [color=green]; - 91 -> {92}; - 92 -> {93}; + 90 -> {91}; - subgraph cluster_19 { + subgraph cluster_18 { color=red - 94 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - 95 [label="Const: String(test_8)"]; - 96 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 92 [label="Enter function test_8" style="filled" fillcolor=red]; + 93 [label="Postponed enter to lambda"]; + 94 [label="Postponed exit from lambda"]; + 95 [label="Function call: R|/myDummyRun|(...)"]; + 96 [label="Exit function test_8" style="filled" fillcolor=red]; } + 92 -> {93}; + 93 -> {94 94} [color=green]; 94 -> {95}; 95 -> {96}; + subgraph cluster_19 { + color=red + 97 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 98 [label="Const: String(test_8)"]; + 99 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + + 97 -> {98}; + 98 -> {99}; + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index d0b7080e78d..545419afdce 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -566,6 +566,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/cfg/emptyWhen.kt"); } + @TestMetadata("flowFromInplaceLambda.kt") + public void testFlowFromInplaceLambda() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.kt"); + } + @TestMetadata("initBlock.kt") public void testInitBlock() throws Exception { runTest("compiler/fir/resolve/testData/resolve/cfg/initBlock.kt"); @@ -576,6 +581,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/cfg/initBlockAndInPlaceLambda.kt"); } + @TestMetadata("inplaceLambdaInControlFlowExpressions.kt") + public void testInplaceLambdaInControlFlowExpressions() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/cfg/inplaceLambdaInControlFlowExpressions.kt"); + } + @TestMetadata("jumps.kt") public void testJumps() throws Exception { runTest("compiler/fir/resolve/testData/resolve/cfg/jumps.kt"); diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 90e5acdc20d..f969031e1cd 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -566,6 +566,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/resolve/testData/resolve/cfg/emptyWhen.kt"); } + @TestMetadata("flowFromInplaceLambda.kt") + public void testFlowFromInplaceLambda() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/cfg/flowFromInplaceLambda.kt"); + } + @TestMetadata("initBlock.kt") public void testInitBlock() throws Exception { runTest("compiler/fir/resolve/testData/resolve/cfg/initBlock.kt"); @@ -596,6 +601,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/resolve/testData/resolve/cfg/loops.kt"); } + @TestMetadata("postponedLambdaInConstructor.kt") + public void testPostponedLambdaInConstructor() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/cfg/postponedLambdaInConstructor.kt"); + } + @TestMetadata("postponedLambdas.kt") public void testPostponedLambdas() throws Exception { runTest("compiler/fir/resolve/testData/resolve/cfg/postponedLambdas.kt");