From 5efd533f55e564aef48bdb70911af3783d4d88ab Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 18 Sep 2020 11:18:50 +0300 Subject: [PATCH] [FIR] Desugar unary plus and minus as part of integer literal #KT-42016 --- .../nonCommutativeRepeat.txt | 2 +- .../emptyRangeChecker/NoWarning.txt | 4 ++-- .../emptyRangeChecker/Warning.txt | 4 ++-- .../resolve/arguments/operatorsOverLiterals.txt | 6 +++--- .../j+k/BasicWithPrimitiveJava.txt | 4 ++-- .../lightTree/converter/ExpressionsConverter.kt | 14 +++++++++++++- .../jetbrains/kotlin/fir/builder/RawFirBuilder.kt | 15 ++++++++++++++- .../evaluate/unaryMinusIndepWoExpType.fir.kt | 6 +++--- .../ir/irText/expressions/literals.fir.txt | 3 +-- .../p-1/neg/2.3.fir.kt | 4 ++-- .../p-1/pos/2.2.fir.kt | 4 ++-- .../p-1/pos/2.3.fir.kt | 4 ++-- .../p-1/pos/2.4.fir.kt | 4 ++-- 13 files changed, 49 insertions(+), 25 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/nonCommutativeRepeat.txt b/compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/nonCommutativeRepeat.txt index a46a3cfb16a..a29f8902953 100644 --- a/compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/nonCommutativeRepeat.txt +++ b/compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/nonCommutativeRepeat.txt @@ -4,5 +4,5 @@ FILE: nonCommutativeRepeat.kt R|/x| = R|/x|.R|kotlin/Int.minus|(Int(1)).R|kotlin/Int.minus|(Int(1)) R|/x| = R|/x|.R|kotlin/Int.div|(Int(1)) R|/x| = Int(1).R|kotlin/Int.div|(R|/x|) - R|/x| = Int(1).R|kotlin/Int.unaryMinus|().R|kotlin/Int.plus|(R|/x|) + R|/x| = Int(-1).R|kotlin/Int.plus|(R|/x|) } diff --git a/compiler/fir/analysis-tests/testData/extendedCheckers/emptyRangeChecker/NoWarning.txt b/compiler/fir/analysis-tests/testData/extendedCheckers/emptyRangeChecker/NoWarning.txt index 220e2394091..6bad4d04889 100644 --- a/compiler/fir/analysis-tests/testData/extendedCheckers/emptyRangeChecker/NoWarning.txt +++ b/compiler/fir/analysis-tests/testData/extendedCheckers/emptyRangeChecker/NoWarning.txt @@ -22,7 +22,7 @@ FILE: NoWarning.kt lval a: R|kotlin/ranges/IntProgression| = Int(4).R|kotlin/ranges/downTo|(Int(3)) lval v: R|kotlin/Int| = Int(1) when () { - Int(5).R|kotlin/Int.unaryMinus|().R|kotlin/ranges/downTo|(Int(6).R|kotlin/Int.unaryMinus|()).R|kotlin/collections/contains|(R|/v|) -> { + Int(-5).R|kotlin/ranges/downTo|(Int(-6)).R|kotlin/collections/contains|(R|/v|) -> { } } @@ -36,7 +36,7 @@ FILE: NoWarning.kt lval a: R|kotlin/ranges/IntRange| = Int(3).R|kotlin/ranges/until|(Int(4)) lval v: R|kotlin/Int| = Int(1) when () { - Int(5).R|kotlin/Int.unaryMinus|().R|kotlin/ranges/until|(Int(4).R|kotlin/Int.unaryMinus|()).R|kotlin/ranges/IntRange.contains|(R|/v|) -> { + Int(-5).R|kotlin/ranges/until|(Int(-4)).R|kotlin/ranges/IntRange.contains|(R|/v|) -> { } } diff --git a/compiler/fir/analysis-tests/testData/extendedCheckers/emptyRangeChecker/Warning.txt b/compiler/fir/analysis-tests/testData/extendedCheckers/emptyRangeChecker/Warning.txt index 7bf1062174f..99630ec9a6b 100644 --- a/compiler/fir/analysis-tests/testData/extendedCheckers/emptyRangeChecker/Warning.txt +++ b/compiler/fir/analysis-tests/testData/extendedCheckers/emptyRangeChecker/Warning.txt @@ -19,7 +19,7 @@ FILE: Warning.kt lval i: R|kotlin/Int| = R|/|.R|kotlin/collections/IntIterator.next|() } - lval a: R|kotlin/ranges/IntProgression| = Int(3).R|kotlin/Int.unaryMinus|().R|kotlin/ranges/downTo|(Int(4)) + lval a: R|kotlin/ranges/IntProgression| = Int(-3).R|kotlin/ranges/downTo|(Int(4)) lval v: R|kotlin/Int| = Int(1) when () { Int(0).R|kotlin/ranges/downTo|(Int(6)).R|kotlin/collections/contains|(R|/v|) -> { @@ -36,7 +36,7 @@ FILE: Warning.kt lval a: R|kotlin/ranges/IntRange| = Int(4).R|kotlin/ranges/until|(Int(3)) lval v: R|kotlin/Int| = Int(1) when () { - Int(5).R|kotlin/Int.unaryMinus|().R|kotlin/ranges/until|(Int(5).R|kotlin/Int.unaryMinus|()).R|kotlin/ranges/IntRange.contains|(R|/v|) -> { + Int(-5).R|kotlin/ranges/until|(Int(-5)).R|kotlin/ranges/IntRange.contains|(R|/v|) -> { } } diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/operatorsOverLiterals.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/operatorsOverLiterals.txt index fb21ec6c31b..3121b69dafb 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/operatorsOverLiterals.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/operatorsOverLiterals.txt @@ -32,7 +32,7 @@ FILE: operatorsOverLiterals.kt R|/takeByte|(Byte(1).R|kotlin/Byte.plus|(Byte(1))) #(Int(1).R|kotlin/Int.plus|(Int(127))) R|/takeByte|(Byte(1).R|kotlin/Byte.minus|(Byte(1))) - #(Int(100).R|kotlin/Int.unaryMinus|().R|kotlin/Int.minus|(Int(100))) + #(Int(-100).R|kotlin/Int.minus|(Int(100))) R|/takeByte|(Byte(10).R|kotlin/Byte.times|(Byte(10))) #(Int(100).R|kotlin/Int.times|(Int(100))) #(Int(10).R|kotlin/Int.div|(Int(10))) @@ -46,8 +46,8 @@ FILE: operatorsOverLiterals.kt #(Int(512).R|kotlin/Int.xor|(Int(511))) } public final fun test_5(): R|kotlin/Unit| { - R|/takeByte|(Byte(1).R|kotlin/Byte.unaryMinus|()) - R|/takeByte|(Byte(1).R|kotlin/Byte.unaryPlus|()) + R|/takeByte|(Byte(-1)) + R|/takeByte|(Byte(1)) R|/takeByte|(Byte(1).R|/inv|()) } public final fun test_6(): R|kotlin/Unit| { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/BasicWithPrimitiveJava.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/BasicWithPrimitiveJava.txt index 58d4b14e15b..ed62ac94baf 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/BasicWithPrimitiveJava.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/BasicWithPrimitiveJava.txt @@ -6,8 +6,8 @@ FILE: jvm.kt public final fun test(): R|kotlin/Unit| { lval res1: R|kotlin/Boolean| = this@R|/A|.R|/Some.foo|(Int(1)) - lval res2: R|kotlin/Boolean| = this@R|/A|.R|/Some.foo|(Int(1).R|kotlin/Int.unaryMinus|()) - lval res3: R|ft!>, kotlin/Array!>?>!| = this@R|/A|.R|/Some.bar|(R|kotlin/intArrayOf|(vararg(Int(0), Int(2), Int(2).R|kotlin/Int.unaryMinus|()))) + lval res2: R|kotlin/Boolean| = this@R|/A|.R|/Some.foo|(Int(-1)) + lval res3: R|ft!>, kotlin/Array!>?>!| = this@R|/A|.R|/Some.bar|(R|kotlin/intArrayOf|(vararg(Int(0), Int(2), Int(-2)))) } } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index 9d60ad5d0ea..9aacd5ea082 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -368,13 +368,25 @@ class ExpressionsConverter( prefix = unaryExpression.tokenType == PREFIX_EXPRESSION ) { getAsFirExpression(this) } } + val receiver = getAsFirExpression(argument, "No operand") + if (operationToken == PLUS || operationToken == MINUS) { + if (receiver is FirConstExpression<*> && receiver.kind == FirConstKind.IntegerLiteral) { + val value = receiver.value as Long + val convertedValue = when (operationToken) { + MINUS -> -value + PLUS -> value + else -> error("Should not be here") + } + return buildConstExpression(unaryExpression.toFirSourceElement(), FirConstKind.IntegerLiteral, convertedValue) + } + } buildFunctionCall { source = unaryExpression.toFirSourceElement() calleeReference = buildSimpleNamedReference { source = this@buildFunctionCall.source name = conventionCallName } - explicitReceiver = getAsFirExpression(argument, "No operand") + explicitReceiver = receiver } } else -> throw IllegalStateException("Unexpected expression: ${unaryExpression.asText}") diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index b8c472d58d3..0ae2713e48e 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -1746,13 +1746,26 @@ class RawFirBuilder( prefix = expression is KtPrefixExpression, ) { (this as KtExpression).toFirExpression("Incorrect expression inside inc/dec") } } + + val receiver = argument.toFirExpression("No operand") + if (operationToken == PLUS || operationToken == MINUS) { + if (receiver is FirConstExpression<*> && receiver.kind == FirConstKind.IntegerLiteral) { + val value = receiver.value as Long + val convertedValue = when (operationToken) { + MINUS -> -value + PLUS -> value + else -> error("Should not be here") + } + return buildConstExpression(expression.toFirPsiSourceElement(), FirConstKind.IntegerLiteral, convertedValue) + } + } buildFunctionCall { source = expression.toFirSourceElement() calleeReference = buildSimpleNamedReference { source = expression.operationReference.toFirSourceElement() name = conventionCallName } - explicitReceiver = argument.toFirExpression("No operand") + explicitReceiver = receiver } } else -> throw IllegalStateException("Unexpected expression: ${expression.text}") diff --git a/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndepWoExpType.fir.kt b/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndepWoExpType.fir.kt index 4e2b30d44b0..6e72ce11f08 100644 --- a/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndepWoExpType.fir.kt +++ b/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndepWoExpType.fir.kt @@ -16,14 +16,14 @@ fun test() { fooInt(p3) fooInt(p4) fooInt(p5) - fooInt(p6) + fooInt(p6) fooLong(p1) fooLong(p2) fooLong(p3) fooLong(p4) fooLong(p5) - fooLong(p6) + fooLong(p6) fooShort(p1) fooShort(p2) @@ -38,4 +38,4 @@ fun test() { fooByte(p4) fooByte(p5) fooByte(p6) -} \ No newline at end of file +} diff --git a/compiler/testData/ir/irText/expressions/literals.fir.txt b/compiler/testData/ir/irText/expressions/literals.fir.txt index c3f20bf2c8b..5bfa9c46544 100644 --- a/compiler/testData/ir/irText/expressions/literals.fir.txt +++ b/compiler/testData/ir/irText/expressions/literals.fir.txt @@ -11,8 +11,7 @@ FILE fqName: fileName:/literals.kt PROPERTY name:test2 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:private [final,static] EXPRESSION_BODY - CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null - $this: CONST Int type=kotlin.Int value=1 + CONST Int type=kotlin.Int value=-1 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [val] BLOCK_BODY diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/neg/2.3.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/neg/2.3.fir.kt index 40f41bd4986..0a202b59a59 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/neg/2.3.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/neg/2.3.fir.kt @@ -79,7 +79,7 @@ fun case_4() { checkSubtype(-2147483649) -2147483649 checkType { check() } -2147483649 checkType { check() } - -2147483649 checkType { check() } + -2147483649 checkType { check() } } // TESTCASE NUMBER: 5 @@ -96,7 +96,7 @@ fun case_5() { checkSubtype(-9223372036854775807) -9223372036854775807 checkType { check() } -9223372036854775807 checkType { check() } - -9223372036854775807 checkType { check() } + -9223372036854775807 checkType { check() } } // TESTCASE NUMBER: 6 diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.2.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.2.fir.kt index dd9ece5e2b2..b5c2939db44 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.2.fir.kt @@ -68,7 +68,7 @@ fun case_4() { checkSubtype(-2147483648) checkSubtype(-2147483648) - -2147483649 checkType { check() } + -2147483649 checkType { check() } checkSubtype(-2147483649) } @@ -77,6 +77,6 @@ fun case_5() { 9223372036854775807 checkType { check() } checkSubtype(9223372036854775807) - -9223372036854775807 checkType { check() } + -9223372036854775807 checkType { check() } checkSubtype(-9223372036854775807) } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.3.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.3.fir.kt index 62c9bcc60c7..45b6da813ab 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.3.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.3.fir.kt @@ -68,7 +68,7 @@ fun case_4() { checkSubtype(-0x80000000) checkSubtype(-0x80000000) - -0x80000001 checkType { check() } + -0x80000001 checkType { check() } checkSubtype(-0x80000001) } @@ -77,6 +77,6 @@ fun case_5() { 0X7FFFFFFFFFFFFFFF checkType { check() } checkSubtype(0X7FFFFFFFFFFFFFFF) - -0X7FFFFFFFFFFFFFFF checkType { check() } + -0X7FFFFFFFFFFFFFFF checkType { check() } checkSubtype(-0X7FFFFFFFFFFFFFFF) } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.4.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.4.fir.kt index 4bac1e36f61..9a7cc0bd82b 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.4.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/the-types-for-integer-literals/p-1/pos/2.4.fir.kt @@ -68,7 +68,7 @@ fun case_4() { checkSubtype(-0B10000000000000000000000000000000) checkSubtype(-0B10000000000000000000000000000000) - -0b10000000000000000000000000000001 checkType { check() } + -0b10000000000000000000000000000001 checkType { check() } checkSubtype(-0b10000000000000000000000000000001) } @@ -77,6 +77,6 @@ fun case_5() { 0b111111111111111111111111111111111111111111111111111111111111111 checkType { check() } checkSubtype(0b111111111111111111111111111111111111111111111111111111111111111) - -0B111111111111111111111111111111111111111111111111111111111111111 checkType { check() } + -0B111111111111111111111111111111111111111111111111111111111111111 checkType { check() } checkSubtype(-0B111111111111111111111111111111111111111111111111111111111111111) }