From 434444cd699aaa9e748a5fdc8b45177014cc444f Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 26 Feb 2020 16:45:57 +0300 Subject: [PATCH] FIR: Support FirComparisonOperator in body transformers and DFA ^KT-31163 In Progress --- .../fir/resolve/dfa/FirDataFlowAnalyzer.kt | 4 + .../fir/resolve/dfa/cfg/ControlFlowGraph.kt | 1 + .../dfa/cfg/ControlFlowGraphBuilder.kt | 6 +- .../dfa/cfg/ControlFlowGraphRenderer.kt | 3 +- .../body/resolve/FirBodyResolveTransformer.kt | 7 + .../FirExpressionsResolveTransformer.kt | 9 + compiler/fir/resolve/testData/resolve/fib.txt | 2 +- .../resolve/samConstructors/kotlinSam.txt | 6 +- .../realConstructorFunction.txt | 6 +- .../resolve/samConstructors/simple.txt | 6 +- .../resolve/samConversions/kotlinSam.kt | 4 +- .../resolve/samConversions/kotlinSam.txt | 10 +- .../notSamBecauseOfSupertype.kt | 4 +- .../notSamBecauseOfSupertype.txt | 6 +- .../resolve/samConversions/samSupertype.txt | 6 +- .../samSupertypeWithOverride.txt | 6 +- .../resolve/samConversions/simple.txt | 6 +- .../callableReferences/ifWithCR.txt | 2 +- .../contracts/callsInPlace.dot | 200 +++++++++--------- .../contracts/callsInPlace.txt | 4 +- .../org/jetbrains/kotlin/fir/FirRenderer.kt | 6 + .../tests/BinaryCallsOnNullableValues.fir.kt | 4 +- .../tests/CompareToWithErrorType.fir.kt | 4 +- .../noAnnotationInClassPath.fir.kt | 2 +- .../calleeExpressionAsCallExpression.fir.kt | 2 +- .../tests/recovery/absentLeftHandSide.fir.kt | 6 +- .../tests/regressions/DoubleDefine.fir.kt | 2 +- .../tests/regressions/kt10843.fir.kt | 2 +- ...castOnSameFieldOfDifferentInstances.fir.kt | 4 +- .../smartcasts/forEachUnsafe.fir.kt | 4 +- .../compiler/visualizer/FirVisualizer.kt | 6 + 31 files changed, 191 insertions(+), 149 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index 708d7842ec0..22d805bff06 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 @@ -233,6 +233,10 @@ abstract class FirDataFlowAnalyzer( node.flow = flow } + fun exitComparisonExpressionCall(comparisonExpression: FirComparisonExpression) { + graphBuilder.exitComparisonExpression(comparisonExpression).mergeIncomingFlow() + } + fun exitOperatorCall(operatorCall: FirOperatorCall) { val node = graphBuilder.exitOperatorCall(operatorCall).mergeIncomingFlow() when (val operation = operatorCall.operation) { 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 eb883e1a7ee..13cc768952a 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 @@ -180,6 +180,7 @@ class BinaryOrExitNode(owner: ControlFlowGraph, override val fir: FirBinaryLogic class TypeOperatorCallNode(owner: ControlFlowGraph, override val fir: FirTypeOperatorCall, level: Int, id: Int) : CFGNode(owner, level, id) class OperatorCallNode(owner: ControlFlowGraph, override val fir: FirOperatorCall, level: Int, id: Int) : AbstractBinaryExitNode(owner, level, id) +class ComparisonExpressionNode(owner: ControlFlowGraph, override val fir: FirComparisonExpression, level: Int, id: Int) : CFGNode(owner, level, id) // ----------------------------------- Jump ----------------------------------- 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 5d431ee1ee0..8b497f7a6f8 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 @@ -256,6 +256,10 @@ class ControlFlowGraphBuilder { return createOperatorCallNode(operatorCall).also { addNewSimpleNode(it) } } + fun exitComparisonExpression(comparisonExpression: FirComparisonExpression): ComparisonExpressionNode { + return ComparisonExpressionNode(graph, comparisonExpression, levelCounter, createId()).also { addNewSimpleNode(it) } + } + // ----------------------------------- Jump ----------------------------------- fun exitJump(jump: FirJump<*>): JumpNode { @@ -723,4 +727,4 @@ class ControlFlowGraphBuilder { fun reset() { exitsOfAnonymousFunctions.clear() } -} \ No newline at end of file +} 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 8118f5634c0..326d414832a 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 @@ -159,6 +159,7 @@ private fun CFGNode<*>.render(): String = is QualifiedAccessNode -> "Access variable ${fir.calleeReference.render(FirRenderer.RenderMode.DontRenderLambdaBodies)}" is OperatorCallNode -> "Operator ${fir.operation.operator}" + is ComparisonExpressionNode -> "Comparison ${fir.operation.operator}" is TypeOperatorCallNode -> "Type operator: \"${fir.render(FirRenderer.RenderMode.DontRenderLambdaBodies)}\"" is JumpNode -> "Jump: ${fir.render()}" is StubNode -> "Stub" @@ -244,4 +245,4 @@ private fun ControlFlowGraph.sortNodes(): List> { } } -private fun List>.indicesMap(): Map, Int> = mapIndexed { i, node -> node to i }.toMap() \ No newline at end of file +private fun List>.indicesMap(): Map, Int> = mapIndexed { i, node -> node to i }.toMap() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt index ef4ea97e8cd..1399445af63 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt @@ -106,6 +106,13 @@ open class FirBodyResolveTransformer( return expressionsTransformer.transformThisReceiverExpression(thisReceiverExpression, data) } + override fun transformComparisonExpression( + comparisonExpression: FirComparisonExpression, + data: ResolutionMode + ): CompositeTransformResult { + return expressionsTransformer.transformComparisonExpression(comparisonExpression, data) + } + override fun transformOperatorCall(operatorCall: FirOperatorCall, data: ResolutionMode): CompositeTransformResult { return expressionsTransformer.transformOperatorCall(operatorCall, data) } 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 8d2573893aa..8ce75a54ce8 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 @@ -208,6 +208,15 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : return transformQualifiedAccessExpression(thisReceiverExpression, data) } + override fun transformComparisonExpression( + comparisonExpression: FirComparisonExpression, + data: ResolutionMode + ): CompositeTransformResult { + return (comparisonExpression.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirComparisonExpression).also { + it.resultType = comparisonExpression.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type) + }.transformSingle(integerLiteralTypeApproximator, null).also(dataFlowAnalyzer::exitComparisonExpressionCall).compose() + } + override fun transformOperatorCall(operatorCall: FirOperatorCall, data: ResolutionMode): CompositeTransformResult { if (operatorCall.operation in FirOperation.BOOLEANS) { // TODO: add approximation of integer literals diff --git a/compiler/fir/resolve/testData/resolve/fib.txt b/compiler/fir/resolve/testData/resolve/fib.txt index 39745d8a2ad..c385a74db75 100644 --- a/compiler/fir/resolve/testData/resolve/fib.txt +++ b/compiler/fir/resolve/testData/resolve/fib.txt @@ -1,7 +1,7 @@ FILE: fib.kt public final fun fibIterative(n: R|kotlin/Int|): R|kotlin/Int| { when () { - <(R|/n|, Int(2)) -> { + CMP(<, R|/n|.R|kotlin/Int.compareTo|(Int(2))) -> { ^fibIterative Int(1) } } diff --git a/compiler/fir/resolve/testData/resolve/samConstructors/kotlinSam.txt b/compiler/fir/resolve/testData/resolve/samConstructors/kotlinSam.txt index e2715740b26..31ce0ce6794 100644 --- a/compiler/fir/resolve/testData/resolve/samConstructors/kotlinSam.txt +++ b/compiler/fir/resolve/testData/resolve/samConstructors/kotlinSam.txt @@ -7,15 +7,15 @@ FILE: kotlinSam.kt } public final fun main(): R|kotlin/Unit| { R|/foo|(R|/MyRunnable|( = MyRunnable@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } )) R|/foo|(R|/MyRunnable|(MyRunnable@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/it|, Int(1)) + ^ CMP(>, R|/it|.R|kotlin/Int.compareTo|(Int(1))) } )) lval x: R|(kotlin/Int) -> kotlin/Boolean| = fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } R|/foo|(R|/MyRunnable|(R|/x|)) diff --git a/compiler/fir/resolve/testData/resolve/samConstructors/realConstructorFunction.txt b/compiler/fir/resolve/testData/resolve/samConstructors/realConstructorFunction.txt index e516b219d71..bd33352729b 100644 --- a/compiler/fir/resolve/testData/resolve/samConstructors/realConstructorFunction.txt +++ b/compiler/fir/resolve/testData/resolve/samConstructors/realConstructorFunction.txt @@ -6,15 +6,15 @@ FILE: main.kt } public final fun main(): R|kotlin/Unit| { #(R|/MyRunnable|( = MyRunnable@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } )) #(R|/MyRunnable|(MyRunnable@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/it|, Int(1)) + ^ CMP(>, R|/it|.R|kotlin/Int.compareTo|(Int(1))) } )) lval x: R|(kotlin/Int) -> kotlin/Boolean| = fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } #(R|/MyRunnable|(R|/x|)) diff --git a/compiler/fir/resolve/testData/resolve/samConstructors/simple.txt b/compiler/fir/resolve/testData/resolve/samConstructors/simple.txt index 229279c7691..810740173ab 100644 --- a/compiler/fir/resolve/testData/resolve/samConstructors/simple.txt +++ b/compiler/fir/resolve/testData/resolve/samConstructors/simple.txt @@ -3,15 +3,15 @@ FILE: main.kt } public final fun main(): R|kotlin/Unit| { R|/foo|(R|/MyRunnable|( = MyRunnable@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } )) R|/foo|(R|/MyRunnable|(MyRunnable@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/it|, Int(1)) + ^ CMP(>, R|/it|.R|kotlin/Int.compareTo|(Int(1))) } )) lval x: R|(kotlin/Int) -> kotlin/Boolean| = fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } R|/foo|(R|/MyRunnable|(R|/x|)) diff --git a/compiler/fir/resolve/testData/resolve/samConversions/kotlinSam.kt b/compiler/fir/resolve/testData/resolve/samConversions/kotlinSam.kt index 9c845a22a6e..9a970c71325 100644 --- a/compiler/fir/resolve/testData/resolve/samConversions/kotlinSam.kt +++ b/compiler/fir/resolve/testData/resolve/samConversions/kotlinSam.kt @@ -30,10 +30,10 @@ fun main() { foo1 { x -> x > 1 } foo1(f) - foo2 { x -> x > 1 } + foo2 { x -> x > 1 } foo2(f) - foo3 { x -> x > 1 } + foo3 { x -> x > 1 } foo3(f) foo4 { x -> x > 1 } diff --git a/compiler/fir/resolve/testData/resolve/samConversions/kotlinSam.txt b/compiler/fir/resolve/testData/resolve/samConversions/kotlinSam.txt index 95bc5690632..a2a4cdd056e 100644 --- a/compiler/fir/resolve/testData/resolve/samConversions/kotlinSam.txt +++ b/compiler/fir/resolve/testData/resolve/samConversions/kotlinSam.txt @@ -30,26 +30,26 @@ FILE: kotlinSam.kt } public final fun main(): R|kotlin/Unit| { lval f: R|(kotlin/Int) -> kotlin/Boolean| = fun (t: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/t|, Int(1)) + ^ CMP(>, R|/t|.R|kotlin/Int.compareTo|(Int(1))) } R|/foo1|( = foo1@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } ) R|/foo1|(R|/f|) #( = foo2@fun (x: R|ERROR CLASS: No type for parameter|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.#(Int(1))) } ) #(R|/f|) #( = foo3@fun (x: R|ERROR CLASS: No type for parameter|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.#(Int(1))) } ) #(R|/f|) R|/foo4|( = foo4@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } ) R|/foo4|(R|/f|) diff --git a/compiler/fir/resolve/testData/resolve/samConversions/notSamBecauseOfSupertype.kt b/compiler/fir/resolve/testData/resolve/samConversions/notSamBecauseOfSupertype.kt index cdce25c7845..016843b8718 100644 --- a/compiler/fir/resolve/testData/resolve/samConversions/notSamBecauseOfSupertype.kt +++ b/compiler/fir/resolve/testData/resolve/samConversions/notSamBecauseOfSupertype.kt @@ -20,10 +20,10 @@ fun foo(m: MyRunnable) {} fun main() { JavaUsage.foo { x -> - x > 1 + x > 1 } - JavaUsage.foo({ it > 1 }) + JavaUsage.foo({ it > 1 }) val x = { x: Int -> x > 1 } diff --git a/compiler/fir/resolve/testData/resolve/samConversions/notSamBecauseOfSupertype.txt b/compiler/fir/resolve/testData/resolve/samConversions/notSamBecauseOfSupertype.txt index 0b88c880c4c..e5a92e09593 100644 --- a/compiler/fir/resolve/testData/resolve/samConversions/notSamBecauseOfSupertype.txt +++ b/compiler/fir/resolve/testData/resolve/samConversions/notSamBecauseOfSupertype.txt @@ -3,15 +3,15 @@ FILE: main.kt } public final fun main(): R|kotlin/Unit| { Q|JavaUsage|.#( = foo@fun (x: R|ERROR CLASS: No type for parameter|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.#(Int(1))) } ) Q|JavaUsage|.#(foo@fun (): R|kotlin/Boolean| { - ^ >(#, Int(1)) + ^ CMP(>, #.#(Int(1))) } ) lval x: R|(kotlin/Int) -> kotlin/Boolean| = fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } Q|JavaUsage|.#(R|/x|) diff --git a/compiler/fir/resolve/testData/resolve/samConversions/samSupertype.txt b/compiler/fir/resolve/testData/resolve/samConversions/samSupertype.txt index e53f958ae19..e4fd224375b 100644 --- a/compiler/fir/resolve/testData/resolve/samConversions/samSupertype.txt +++ b/compiler/fir/resolve/testData/resolve/samConversions/samSupertype.txt @@ -3,15 +3,15 @@ FILE: main.kt } public final fun main(): R|kotlin/Unit| { Q|JavaUsage|.R|/JavaUsage.foo|( = foo@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } ) Q|JavaUsage|.R|/JavaUsage.foo|(foo@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/it|, Int(1)) + ^ CMP(>, R|/it|.R|kotlin/Int.compareTo|(Int(1))) } ) lval x: R|(kotlin/Int) -> kotlin/Boolean| = fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } Q|JavaUsage|.R|/JavaUsage.foo|(R|/x|) diff --git a/compiler/fir/resolve/testData/resolve/samConversions/samSupertypeWithOverride.txt b/compiler/fir/resolve/testData/resolve/samConversions/samSupertypeWithOverride.txt index 4fffa4c2f05..b3cda246e11 100644 --- a/compiler/fir/resolve/testData/resolve/samConversions/samSupertypeWithOverride.txt +++ b/compiler/fir/resolve/testData/resolve/samConversions/samSupertypeWithOverride.txt @@ -3,15 +3,15 @@ FILE: main.kt } public final fun main(): R|kotlin/Unit| { Q|JavaUsage|.R|/JavaUsage.foo|( = foo@fun (x: R|kotlin/Int|): R|ft!| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } ) Q|JavaUsage|.R|/JavaUsage.foo|(foo@fun (it: R|kotlin/Int|): R|ft!| { - ^ >(R|/it|, Int(1)) + ^ CMP(>, R|/it|.R|kotlin/Int.compareTo|(Int(1))) } ) lval x: R|(kotlin/Int) -> kotlin/Boolean| = fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } Q|JavaUsage|.R|/JavaUsage.foo|(R|/x|) diff --git a/compiler/fir/resolve/testData/resolve/samConversions/simple.txt b/compiler/fir/resolve/testData/resolve/samConversions/simple.txt index e53f958ae19..e4fd224375b 100644 --- a/compiler/fir/resolve/testData/resolve/samConversions/simple.txt +++ b/compiler/fir/resolve/testData/resolve/samConversions/simple.txt @@ -3,15 +3,15 @@ FILE: main.kt } public final fun main(): R|kotlin/Unit| { Q|JavaUsage|.R|/JavaUsage.foo|( = foo@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } ) Q|JavaUsage|.R|/JavaUsage.foo|(foo@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/it|, Int(1)) + ^ CMP(>, R|/it|.R|kotlin/Int.compareTo|(Int(1))) } ) lval x: R|(kotlin/Int) -> kotlin/Boolean| = fun (x: R|kotlin/Int|): R|kotlin/Boolean| { - ^ >(R|/x|, Int(1)) + ^ CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) } Q|JavaUsage|.R|/JavaUsage.foo|(R|/x|) diff --git a/compiler/fir/resolve/testData/resolveWithStdlib/callableReferences/ifWithCR.txt b/compiler/fir/resolve/testData/resolveWithStdlib/callableReferences/ifWithCR.txt index 6121638a0ec..f032f5ec90a 100644 --- a/compiler/fir/resolve/testData/resolveWithStdlib/callableReferences/ifWithCR.txt +++ b/compiler/fir/resolve/testData/resolveWithStdlib/callableReferences/ifWithCR.txt @@ -11,7 +11,7 @@ FILE: ifWithCR.kt private set(value: R|kotlin/CharSequence?|): R|kotlin/Unit| public final fun main(x: R|kotlin/Int|): R|kotlin/Unit| { lval x: R|kotlin/reflect/KMutableProperty0| = when () { - >(R|/x|, Int(1)) -> { + CMP(>, R|/x|.R|kotlin/Int.compareTo|(Int(1))) -> { R|/x|::R|/readOnlyWrapper| } else -> { diff --git a/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.dot b/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.dot index 767bcfc5bd2..85360b862b7 100644 --- a/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.dot +++ b/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.dot @@ -100,183 +100,187 @@ digraph callsInPlace_kt { 34 [label="Const: String(test_4)"]; 35 [label="Access variable R|/it|"]; 36 [label="Const: Int(0)"]; - 37 [label="Operator >"]; - 38 [label="Exit function anonymousFunction"]; + 37 [label="Function call: R|/it|.R|kotlin/Int.compareTo|(Int(0))"]; + 38 [label="Comparison >"]; + 39 [label="Exit function anonymousFunction"]; } - 39 [label="Postponed exit from lambda"]; - 40 [label="Function call: Int(1).R|kotlin/takeUnless|( = takeUnless@fun (it: R|kotlin/Int|): R|kotlin/Boolean| )"]; - 41 [label="Exit function test_4" style="filled" fillcolor=red]; + 40 [label="Postponed exit from lambda"]; + 41 [label="Function call: Int(1).R|kotlin/takeUnless|( = takeUnless@fun (it: R|kotlin/Int|): R|kotlin/Boolean| )"]; + 42 [label="Exit function test_4" style="filled" fillcolor=red]; } 30 -> {31}; 31 -> {32}; 32 -> {33}; - 32 -> {39} [color=red]; + 32 -> {40} [color=red]; 33 -> {34}; 34 -> {35}; 35 -> {36}; 36 -> {37}; 37 -> {38}; - 38 -> {39} [color=green]; - 39 -> {40}; + 38 -> {39}; + 39 -> {40} [color=green]; 40 -> {41}; + 41 -> {42}; subgraph cluster_8 { color=red - 42 [label="Enter function test_5" style="filled" fillcolor=red]; - 43 [label="Const: Int(1)"]; - 44 [label="Postponed enter to lambda"]; + 43 [label="Enter function test_5" style="filled" fillcolor=red]; + 44 [label="Const: Int(1)"]; + 45 [label="Postponed enter to lambda"]; subgraph cluster_9 { color=blue - 45 [label="Enter function anonymousFunction"]; - 46 [label="Const: String(test_5)"]; - 47 [label="Access variable R|/it|"]; - 48 [label="Const: Int(0)"]; - 49 [label="Operator >"]; - 50 [label="Exit function anonymousFunction"]; + 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|(Int(0))"]; + 51 [label="Comparison >"]; + 52 [label="Exit function anonymousFunction"]; } - 51 [label="Postponed exit from lambda"]; - 52 [label="Function call: Int(1).R|kotlin/takeUnless|(predicate = takeUnless@fun (it: R|kotlin/Int|): R|kotlin/Boolean| )"]; - 53 [label="Exit function test_5" style="filled" fillcolor=red]; + 53 [label="Postponed exit from lambda"]; + 54 [label="Function call: Int(1).R|kotlin/takeUnless|(predicate = takeUnless@fun (it: R|kotlin/Int|): R|kotlin/Boolean| )"]; + 55 [label="Exit function test_5" style="filled" fillcolor=red]; } - 42 -> {43}; 43 -> {44}; 44 -> {45}; - 44 -> {51} [color=red]; 45 -> {46}; + 45 -> {53} [color=red]; 46 -> {47}; 47 -> {48}; 48 -> {49}; 49 -> {50}; - 50 -> {51} [color=green]; + 50 -> {51}; 51 -> {52}; - 52 -> {53}; + 52 -> {53} [color=green]; + 53 -> {54}; + 54 -> {55}; subgraph cluster_10 { color=red - 54 [label="Enter function myRun" style="filled" fillcolor=red]; - 55 [label="Function call: R|/block1|.R|FakeOverride|()"]; - 56 [label="Function call: R|/block2|.R|FakeOverride|()"]; - 57 [label="Exit function myRun" style="filled" fillcolor=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]; } - 54 -> {55}; - 55 -> {56}; 56 -> {57}; + 57 -> {58}; + 58 -> {59}; subgraph cluster_11 { color=red - 58 [label="Enter function test_6" style="filled" fillcolor=red]; - 59 [label="Postponed enter to lambda"]; + 60 [label="Enter function test_6" style="filled" fillcolor=red]; + 61 [label="Postponed enter to lambda"]; subgraph cluster_12 { color=blue - 60 [label="Enter function anonymousFunction"]; - 61 [label="Const: String(test_6_1)"]; - 62 [label="Exit function anonymousFunction"]; + 62 [label="Enter function anonymousFunction"]; + 63 [label="Const: String(test_6_1)"]; + 64 [label="Exit function anonymousFunction"]; } - 63 [label="Postponed exit from lambda"]; - 64 [label="Postponed enter to lambda"]; + 65 [label="Postponed exit from lambda"]; + 66 [label="Postponed enter to lambda"]; subgraph cluster_13 { color=blue - 65 [label="Enter function anonymousFunction"]; - 66 [label="Const: String(test_6_2)"]; - 67 [label="Exit function anonymousFunction"]; + 67 [label="Enter function anonymousFunction"]; + 68 [label="Const: String(test_6_2)"]; + 69 [label="Exit function anonymousFunction"]; } - 68 [label="Postponed exit from lambda"]; - 69 [label="Function call: R|/myRun|(myRun@fun (): R|kotlin/Unit| , = myRun@fun (): R|kotlin/Unit| )"]; - 70 [label="Exit function test_6" style="filled" fillcolor=red]; + 70 [label="Postponed exit from lambda"]; + 71 [label="Function call: R|/myRun|(myRun@fun (): R|kotlin/Unit| , = myRun@fun (): R|kotlin/Unit| )"]; + 72 [label="Exit function test_6" style="filled" fillcolor=red]; } - 58 -> {59}; - 59 -> {60}; - 59 -> {63} [color=red]; - 60 -> {62 61}; + 60 -> {61}; 61 -> {62}; - 62 -> {60}; - 62 -> {63} [color=green]; + 61 -> {65} [color=red]; + 62 -> {64 63}; 63 -> {64}; - 64 -> {65}; - 64 -> {68} [color=red]; - 65 -> {67 66}; + 64 -> {62}; + 64 -> {65} [color=green]; + 65 -> {66}; 66 -> {67}; - 67 -> {65}; - 67 -> {68} [color=green]; + 66 -> {70} [color=red]; + 67 -> {69 68}; 68 -> {69}; - 69 -> {70}; + 69 -> {67}; + 69 -> {70} [color=green]; + 70 -> {71}; + 71 -> {72}; subgraph cluster_14 { color=red - 71 [label="Enter function test_7" style="filled" fillcolor=red]; - 72 [label="Postponed enter to lambda"]; + 73 [label="Enter function test_7" style="filled" fillcolor=red]; + 74 [label="Postponed enter to lambda"]; subgraph cluster_15 { color=blue - 73 [label="Enter function anonymousFunction"]; - 74 [label="Const: String(test_7_2)"]; - 75 [label="Exit function anonymousFunction"]; + 75 [label="Enter function anonymousFunction"]; + 76 [label="Const: String(test_7_2)"]; + 77 [label="Exit function anonymousFunction"]; } - 76 [label="Postponed exit from lambda"]; - 77 [label="Postponed enter to lambda"]; + 78 [label="Postponed exit from lambda"]; + 79 [label="Postponed enter to lambda"]; subgraph cluster_16 { color=blue - 78 [label="Enter function anonymousFunction"]; - 79 [label="Const: String(test_7_1)"]; - 80 [label="Exit function anonymousFunction"]; + 80 [label="Enter function anonymousFunction"]; + 81 [label="Const: String(test_7_1)"]; + 82 [label="Exit function anonymousFunction"]; } - 81 [label="Postponed exit from lambda"]; - 82 [label="Function call: R|/myRun|(block2 = myRun@fun (): R|kotlin/Unit| , block1 = myRun@fun (): R|kotlin/Unit| )"]; - 83 [label="Exit function test_7" style="filled" fillcolor=red]; + 83 [label="Postponed exit from lambda"]; + 84 [label="Function call: R|/myRun|(block2 = myRun@fun (): R|kotlin/Unit| , block1 = myRun@fun (): R|kotlin/Unit| )"]; + 85 [label="Exit function test_7" style="filled" fillcolor=red]; } - 71 -> {72}; - 72 -> {73}; - 72 -> {76} [color=red]; - 73 -> {75 74}; + 73 -> {74}; 74 -> {75}; - 75 -> {73}; - 75 -> {76} [color=green]; + 74 -> {78} [color=red]; + 75 -> {77 76}; 76 -> {77}; - 77 -> {78}; - 77 -> {81} [color=red]; - 78 -> {80 79}; + 77 -> {75}; + 77 -> {78} [color=green]; + 78 -> {79}; 79 -> {80}; - 80 -> {78}; - 80 -> {81} [color=green]; + 79 -> {83} [color=red]; + 80 -> {82 81}; 81 -> {82}; - 82 -> {83}; + 82 -> {80}; + 82 -> {83} [color=green]; + 83 -> {84}; + 84 -> {85}; subgraph cluster_17 { color=red - 84 [label="Enter function myDummyRun" style="filled" fillcolor=red]; - 85 [label="Function call: R|/block|.R|FakeOverride|()"]; - 86 [label="Exit function myDummyRun" style="filled" fillcolor=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]; } - 84 -> {85}; - 85 -> {86}; + 86 -> {87}; + 87 -> {88}; subgraph cluster_18 { color=red - 87 [label="Enter function test_8" style="filled" fillcolor=red]; - 88 [label="Postponed enter to lambda"]; - 89 [label="Postponed exit from lambda"]; - 90 [label="Function call: R|/myDummyRun|( = myDummyRun@fun (): R|kotlin/Unit|)"]; - 91 [label="Exit function test_8" style="filled" fillcolor=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|( = myDummyRun@fun (): R|kotlin/Unit|)"]; + 93 [label="Exit function test_8" style="filled" fillcolor=red]; } - 87 -> {88}; - 88 -> {89 89} [color=green]; 89 -> {90}; - 90 -> {91}; + 90 -> {91 91} [color=green]; + 91 -> {92}; + 92 -> {93}; subgraph cluster_19 { color=red - 92 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - 93 [label="Const: String(test_8)"]; - 94 [label="Exit function anonymousFunction" style="filled" fillcolor=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 -> {93}; - 93 -> {94}; + 94 -> {95}; + 95 -> {96}; } diff --git a/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.txt b/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.txt index f139f1309c7..15ca59afa42 100644 --- a/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.txt +++ b/compiler/fir/resolve/testData/resolveWithStdlib/contracts/callsInPlace.txt @@ -22,14 +22,14 @@ FILE: callsInPlace.kt public final fun test_4(): R|kotlin/Unit| { Int(1).R|kotlin/takeUnless|( = takeUnless@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { String(test_4) - ^ >(R|/it|, Int(0)) + ^ CMP(>, R|/it|.R|kotlin/Int.compareTo|(Int(0))) } ) } public final fun test_5(): R|kotlin/Unit| { Int(1).R|kotlin/takeUnless|(predicate = takeUnless@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { String(test_5) - ^ >(R|/it|, Int(0)) + ^ CMP(>, R|/it|.R|kotlin/Int.compareTo|(Int(0))) } ) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt index d2d3fc44642..4927945bd69 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt @@ -1020,6 +1020,12 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM visitCall(operatorCall) } + override fun visitComparisonExpression(comparisonExpression: FirComparisonExpression) { + print("CMP(${comparisonExpression.operation.operator}, ") + comparisonExpression.compareToCall.accept(this) + print(")") + } + override fun visitComponentCall(componentCall: FirComponentCall) { componentCall.annotations.renderAnnotations() componentCall.explicitReceiver.accept(this) diff --git a/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt b/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt index b0f6947b64e..2fa18ca9642 100644 --- a/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt +++ b/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt @@ -8,7 +8,7 @@ fun f(): Unit { x = null x + 1 x plus 1 - x < 1 + x < 1 x += 1 x == 1 @@ -29,4 +29,4 @@ fun f(): Unit { false || y y && true y && 1 -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/CompareToWithErrorType.fir.kt b/compiler/testData/diagnostics/tests/CompareToWithErrorType.fir.kt index de38f681f4b..316d2bb8dc3 100644 --- a/compiler/testData/diagnostics/tests/CompareToWithErrorType.fir.kt +++ b/compiler/testData/diagnostics/tests/CompareToWithErrorType.fir.kt @@ -1,6 +1,6 @@ // !WITH_NEW_INFERENCE fun test() { - if (x > 0) { + if (x > 0) { } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/platformTypes/noAnnotationInClassPath.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/noAnnotationInClassPath.fir.kt index de64ac8a435..27069db2ec1 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/noAnnotationInClassPath.fir.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/noAnnotationInClassPath.fir.kt @@ -13,5 +13,5 @@ public class B { // FILE: main.kt fun test() { - B.bar() { it.hashCode() > 0 } + B.bar() { it.hashCode() > 0 } } diff --git a/compiler/testData/diagnostics/tests/qualifiedExpression/calleeExpressionAsCallExpression.fir.kt b/compiler/testData/diagnostics/tests/qualifiedExpression/calleeExpressionAsCallExpression.fir.kt index 7bb29de02cb..bcc9b5931bc 100644 --- a/compiler/testData/diagnostics/tests/qualifiedExpression/calleeExpressionAsCallExpression.fir.kt +++ b/compiler/testData/diagnostics/tests/qualifiedExpression/calleeExpressionAsCallExpression.fir.kt @@ -1,2 +1,2 @@ // !WITH_NEW_INFERENCE -val unwrapped = some<sdf()()::unwrap \ No newline at end of file +val unwrapped = some<sdf()()::unwrap diff --git a/compiler/testData/diagnostics/tests/recovery/absentLeftHandSide.fir.kt b/compiler/testData/diagnostics/tests/recovery/absentLeftHandSide.fir.kt index 2a108a6ca91..3919a089238 100644 --- a/compiler/testData/diagnostics/tests/recovery/absentLeftHandSide.fir.kt +++ b/compiler/testData/diagnostics/tests/recovery/absentLeftHandSide.fir.kt @@ -8,9 +8,9 @@ fun composite() { } fun html() { - <html></html> + <html></html> } fun html1() { - <html></html>html -} \ No newline at end of file + <html></html>html +} diff --git a/compiler/testData/diagnostics/tests/regressions/DoubleDefine.fir.kt b/compiler/testData/diagnostics/tests/regressions/DoubleDefine.fir.kt index 222207164de..7d8a798f289 100644 --- a/compiler/testData/diagnostics/tests/regressions/DoubleDefine.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/DoubleDefine.fir.kt @@ -11,7 +11,7 @@ fun takeFirst(expr: StringBuilder): Char { fun evaluateArg(expr: CharSequence, numbers: ArrayList): Int { if (expr.length == 0) throw Exception("Syntax error: Character expected"); val c = takeFirst(expr) - if (c >= '0' && c <= '9') { + if (c >= '0' && c <= '9') { val n = c - '0' if (!numbers.contains(n)) throw Exception("You used incorrect number: " + n) numbers.remove(n) diff --git a/compiler/testData/diagnostics/tests/regressions/kt10843.fir.kt b/compiler/testData/diagnostics/tests/regressions/kt10843.fir.kt index c34a25f506f..d8b434aa4a4 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt10843.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt10843.fir.kt @@ -3,6 +3,6 @@ // See EA-76890 / KT-10843: NPE during analysis fun lambda(x : Int?) = x?.let l { y -> - if (y > 0) return@l x + if (y > 0) return@l x y }!! diff --git a/compiler/testData/diagnostics/tests/smartCasts/smartcastOnSameFieldOfDifferentInstances.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/smartcastOnSameFieldOfDifferentInstances.fir.kt index 63d81705963..0f2d88161aa 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/smartcastOnSameFieldOfDifferentInstances.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/smartcastOnSameFieldOfDifferentInstances.fir.kt @@ -5,7 +5,7 @@ class A(val x: String?) { fun foo(other: A) { when { x == null && other.x == null -> "1" - x.length > 0 -> "2" + x.length > 0 -> "2" } } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/smartcasts/forEachUnsafe.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/smartcasts/forEachUnsafe.fir.kt index 0f1c3381217..30f30de0207 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/smartcasts/forEachUnsafe.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/smartcasts/forEachUnsafe.fir.kt @@ -3,7 +3,7 @@ fun indexOfMax(a: IntArray): Int? { var maxI: Int? = 0 a.forEachIndexed { i, value -> - if (value >= a[maxI]) { + if (value >= a[maxI]) { maxI = i } else if (value < 0) { @@ -11,4 +11,4 @@ fun indexOfMax(a: IntArray): Int? { } } return maxI -} \ No newline at end of file +} diff --git a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt index 7ec748a49ff..58657fd296c 100644 --- a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt +++ b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt @@ -396,6 +396,12 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() { data.append("operator call ${operatorCall.operation}") } + override fun visitComparisonExpression(comparisonExpression: FirComparisonExpression, data: StringBuilder) { + data.append("CMP(${comparisonOperator.operation.operator}, ") + comparisonOperator.compareToCall.accept(this, data) + data.append(")") + } + override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: StringBuilder) { //skip rendering for as/as?/is/!is }