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 cccdb88f60d..b2269cc499b 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 @@ -1030,12 +1030,12 @@ abstract class FirDataFlowAnalyzer( // ----------------------------------- Annotations ----------------------------------- - fun enterAnnotation(annotation: FirAnnotation) { - graphBuilder.enterAnnotation(annotation).mergeIncomingFlow() + fun enterAnnotation() { + graphBuilder.enterFakeExpression().mergeIncomingFlow() } - fun exitAnnotation(annotation: FirAnnotation) { - graphBuilder.exitAnnotation(annotation).mergeIncomingFlow() + fun exitAnnotation() { + graphBuilder.exitFakeExpression() } // ----------------------------------- Init block ----------------------------------- @@ -1053,11 +1053,11 @@ abstract class FirDataFlowAnalyzer( // ----------------------------------- Contract description ----------------------------------- fun enterContractDescription() { - graphBuilder.enterContractDescription().mergeIncomingFlow() + graphBuilder.enterFakeExpression().mergeIncomingFlow() } fun exitContractDescription() { - graphBuilder.exitContractDescription() + graphBuilder.exitFakeExpression() } // ----------------------------------- Elvis ----------------------------------- 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 c65071d816d..2d9f37689c7 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 @@ -1186,20 +1186,23 @@ class ControlFlowGraphBuilder { return node } - // ----------------------------------- Annotations ----------------------------------- + // ----------------------------------- Fake expressions ----------------------------------- - fun enterAnnotation(annotation: FirAnnotation): AnnotationEnterNode { - pushGraph(ControlFlowGraph(null, "STUB_GRAPH_FOR_ANNOTATION_CALL", ControlFlowGraph.Kind.AnnotationCall)) - return createAnnotationEnterNode(annotation).also { + fun enterFakeExpression(): FakeExpressionEnterNode { + // Things like annotations and `contract { ... }` use normal call resolution, but aren't real expressions + // and are never evaluated. We'll push all nodes created in the process into a stub graph, then throw it away. + // TODO: don't waste time creating the nodes in the first place + pushGraph(ControlFlowGraph(null, "STUB_GRAPH_FOR_FAKE_EXPRESSION", ControlFlowGraph.Kind.FakeCall)) + return createFakeExpressionEnterNode().also { lastNodes.push(it) + exitTargetsForTry.push(it) // technically might create CFG loops, but the graph will never be visited anyway... } } - fun exitAnnotation(annotation: FirAnnotation): AnnotationExitNode { - val node = createAnnotationExitNode(annotation) - popAndAddEdge(node) + fun exitFakeExpression() { + lastNodes.pop() + exitTargetsForTry.pop() popGraph() - return node } // ----------------------------------- Callable references ----------------------------------- @@ -1319,23 +1322,6 @@ class ControlFlowGraphBuilder { return exitNode } - // ----------------------------------- Contract description ----------------------------------- - - fun enterContractDescription(): CFGNode<*> { - pushGraph(ControlFlowGraph(null, "contract description", ControlFlowGraph.Kind.AnonymousFunction)) - - return createContractDescriptionEnterNode().also { - lastNodes.push(it) - exitTargetsForTry.push(it) - } - } - - fun exitContractDescription() { - lastNodes.pop() - exitTargetsForTry.pop() - popGraph() - } - // ------------------------------------------------------------------------------------------------------------------------- fun reset() { 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 a0e61ccaae3..be7e11d0c1d 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 @@ -11,8 +11,8 @@ import org.jetbrains.kotlin.fir.expressions.* fun ControlFlowGraphBuilder.createStubNode(): StubNode = StubNode(currentGraph, levelCounter, createId()) -fun ControlFlowGraphBuilder.createContractDescriptionEnterNode(): ContractDescriptionEnterNode = - ContractDescriptionEnterNode(currentGraph, levelCounter, createId()) +fun ControlFlowGraphBuilder.createFakeExpressionEnterNode(): FakeExpressionEnterNode = + FakeExpressionEnterNode(currentGraph, levelCounter, createId()) fun ControlFlowGraphBuilder.createLoopExitNode(fir: FirLoop): LoopExitNode = LoopExitNode(currentGraph, fir, levelCounter, createId()) @@ -145,12 +145,6 @@ fun ControlFlowGraphBuilder.createStringConcatenationCallNode(fir: FirStringConc fun ControlFlowGraphBuilder.createVariableAssignmentNode(fir: FirVariableAssignment): VariableAssignmentNode = VariableAssignmentNode(currentGraph, fir, levelCounter, createId()) -fun ControlFlowGraphBuilder.createAnnotationExitNode(fir: FirAnnotation): AnnotationExitNode = - AnnotationExitNode(currentGraph, fir, levelCounter, createId()) - -fun ControlFlowGraphBuilder.createAnnotationEnterNode(fir: FirAnnotation): AnnotationEnterNode = - AnnotationEnterNode(currentGraph, fir, levelCounter, createId()) - fun ControlFlowGraphBuilder.createElvisLhsIsNotNullNode(fir: FirElvisExpression): ElvisLhsIsNotNullNode = ElvisLhsIsNotNullNode(currentGraph, fir, levelCounter, createId()) 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 b98fc17f6b1..7a09a3c6b10 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 @@ -1098,9 +1098,9 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT annotationCall.replaceAnnotationResolvePhase(FirAnnotationResolvePhase.Types) return context.forAnnotation { withFirArrayOfCallTransformer { - dataFlowAnalyzer.enterAnnotation(annotationCall) + dataFlowAnalyzer.enterAnnotation() val result = callResolver.resolveAnnotationCall(annotationCall) - dataFlowAnalyzer.exitAnnotation(result ?: annotationCall) + dataFlowAnalyzer.exitAnnotation() if (result == null) return annotationCall callCompleter.completeCall(result, noExpectedType) (result.argumentList as FirResolvedArgumentList).let { annotationCall.replaceArgumentMapping((it).toAnnotationArgumentMapping()) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt index 5a514de77ed..b15929473b7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt @@ -143,9 +143,9 @@ private class FirExpressionsResolveTransformerForSpecificAnnotations( ) : FirExpressionsResolveTransformer(transformer) { override fun transformAnnotation(annotation: FirAnnotation, data: ResolutionMode): FirStatement { - dataFlowAnalyzer.enterAnnotation(annotation) + dataFlowAnalyzer.enterAnnotation() annotation.transformChildren(transformer, ResolutionMode.ContextDependent) - dataFlowAnalyzer.exitAnnotation(annotation) + dataFlowAnalyzer.exitAnnotation() return annotation } diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt index 3ea62150e05..444ff5554bf 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt @@ -747,18 +747,6 @@ class StubNode(owner: ControlFlowGraph, level: Int, id: Int) : CFGNode( } } -@OptIn(CfgInternals::class) -class ContractDescriptionEnterNode(owner: ControlFlowGraph, level: Int, id: Int) : CFGNode(owner, level, id) { - init { - owner.enterNode = this - } - - override val fir: FirStub = FirStub - override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { - return visitor.visitContractDescriptionEnterNode(this, data) - } -} - class VariableDeclarationNode(owner: ControlFlowGraph, override val fir: FirProperty, level: Int, id: Int) : CFGNode(owner, level, id) { override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { return visitor.visitVariableDeclarationNode(this, data) @@ -813,32 +801,6 @@ class WhenSubjectExpressionExitNode(owner: ControlFlowGraph, override val fir: F } } -// ----------------------------------- Other ----------------------------------- - -@OptIn(CfgInternals::class) -class AnnotationEnterNode(owner: ControlFlowGraph, override val fir: FirAnnotation, level: Int, id: Int) : CFGNode(owner, level, id), - EnterNodeMarker { - init { - owner.enterNode = this - } - - override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { - return visitor.visitAnnotationEnterNode(this, data) - } -} - -@OptIn(CfgInternals::class) -class AnnotationExitNode(owner: ControlFlowGraph, override val fir: FirAnnotation, level: Int, id: Int) : CFGNode(owner, level, id), - ExitNodeMarker { - init { - owner.exitNode = this - } - - override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { - return visitor.visitAnnotationExitNode(this, data) - } -} - // ----------------------------------- Stub ----------------------------------- object FirStub : FirExpression() { @@ -853,6 +815,16 @@ object FirStub : FirExpression() { override fun replaceTypeRef(newTypeRef: FirTypeRef) { assert(newTypeRef.isNothing) } } +class FakeExpressionEnterNode(owner: ControlFlowGraph, level: Int, id: Int) : CFGNode(owner, level, id) { + init { isDead = true } + + override val fir: FirStub = FirStub + + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { + throw IllegalStateException("fake expressions should not appear in graphs") + } +} + // ----------------------------------- Smart-cast node ----------------------------------- class SmartCastExpressionExitNode(owner: ControlFlowGraph, override val fir: FirSmartCastExpression, level: Int, id: Int) : CFGNode(owner, level, id) { diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt index 40e14676d3e..28483ca6dd5 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt @@ -90,8 +90,6 @@ fun CFGNode<*>.render(): String = is FieldInitializerExitNode -> "Exit field" is InitBlockEnterNode -> "Enter init block" is InitBlockExitNode -> "Exit init block" - is AnnotationEnterNode -> "Enter annotation" - is AnnotationExitNode -> "Exit annotation" is EnterSafeCallNode -> "Enter safe call" is ExitSafeCallNode -> "Exit safe call" @@ -113,7 +111,7 @@ fun CFGNode<*>.render(): String = is ScriptEnterNode -> "Enter class ${fir.name}" is ScriptExitNode -> "Exit class ${fir.name}" - is ContractDescriptionEnterNode -> "Enter contract description" + is FakeExpressionEnterNode -> "Enter fake expression" is EnterValueParameterNode -> "Enter default value of ${fir.name}" is EnterDefaultArgumentsNode -> "Enter default value of ${fir.name}" diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt index fab95f9f7fd..90fe3f92bff 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt @@ -68,7 +68,7 @@ class ControlFlowGraph(val declaration: FirDeclaration?, val name: String, val k PropertyInitializer(withBody = true), FieldInitializer(withBody = true), TopLevel(withBody = false), - AnnotationCall(withBody = true), + FakeCall(withBody = true), DefaultArgument(withBody = true), Stub(withBody = false) } diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt index 1a7fb9ede6d..3744a946bca 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt @@ -347,10 +347,6 @@ abstract class ControlFlowGraphVisitor { return visitNode(node, data) } - open fun visitContractDescriptionEnterNode(node: ContractDescriptionEnterNode, data: D): R { - return visitNode(node, data) - } - open fun visitVariableDeclarationNode(node: VariableDeclarationNode, data: D): R { return visitNode(node, data) } @@ -391,14 +387,6 @@ abstract class ControlFlowGraphVisitor { // ----------------------------------- Other ----------------------------------- - open fun visitAnnotationEnterNode(node: AnnotationEnterNode, data: D): R { - return visitNode(node, data) - } - - open fun visitAnnotationExitNode(node: AnnotationExitNode, data: D): R { - return visitNode(node, data) - } - open fun visitSmartCastExpressionExitNode(node: SmartCastExpressionExitNode, data: D): R { return visitNode(node, data) } diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitorVoid.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitorVoid.kt index f27ca0ecdf3..dd6f7f835ab 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitorVoid.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitorVoid.kt @@ -291,16 +291,6 @@ abstract class ControlFlowGraphVisitorVoid : ControlFlowGraphVisitor, data: Nothing?) { @@ -591,14 +581,4 @@ abstract class ControlFlowGraphVisitorVoid : ControlFlowGraphVisitor