[FIR] Desugar unary plus and minus as part of integer literal

#KT-42016
This commit is contained in:
Dmitriy Novozhilov
2020-09-18 11:18:50 +03:00
parent a018847f85
commit 5efd533f55
13 changed files with 49 additions and 25 deletions

View File

@@ -4,5 +4,5 @@ FILE: nonCommutativeRepeat.kt
R|<local>/x| = R|<local>/x|.R|kotlin/Int.minus|(Int(1)).R|kotlin/Int.minus|(Int(1))
R|<local>/x| = R|<local>/x|.R|kotlin/Int.div|(Int(1))
R|<local>/x| = Int(1).R|kotlin/Int.div|(R|<local>/x|)
R|<local>/x| = Int(1).R|kotlin/Int.unaryMinus|().R|kotlin/Int.plus|(R|<local>/x|)
R|<local>/x| = Int(-1).R|kotlin/Int.plus|(R|<local>/x|)
}

View File

@@ -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|kotlin/Int|>(R|<local>/v|) -> {
Int(-5).R|kotlin/ranges/downTo|(Int(-6)).R|kotlin/collections/contains|<R|kotlin/Int|>(R|<local>/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|<local>/v|) -> {
Int(-5).R|kotlin/ranges/until|(Int(-4)).R|kotlin/ranges/IntRange.contains|(R|<local>/v|) -> {
}
}

View File

@@ -19,7 +19,7 @@ FILE: Warning.kt
lval i: R|kotlin/Int| = R|<local>/<iterator>|.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|kotlin/Int|>(R|<local>/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|<local>/v|) -> {
Int(-5).R|kotlin/ranges/until|(Int(-5)).R|kotlin/ranges/IntRange.contains|(R|<local>/v|) -> {
}
}

View File

@@ -32,7 +32,7 @@ FILE: operatorsOverLiterals.kt
R|/takeByte|(Byte(1).R|kotlin/Byte.plus|(Byte(1)))
<Inapplicable(INAPPLICABLE): /takeByte>#(Int(1).R|kotlin/Int.plus|(Int(127)))
R|/takeByte|(Byte(1).R|kotlin/Byte.minus|(Byte(1)))
<Inapplicable(INAPPLICABLE): /takeByte>#(Int(100).R|kotlin/Int.unaryMinus|().R|kotlin/Int.minus|(Int(100)))
<Inapplicable(INAPPLICABLE): /takeByte>#(Int(-100).R|kotlin/Int.minus|(Int(100)))
R|/takeByte|(Byte(10).R|kotlin/Byte.times|(Byte(10)))
<Inapplicable(INAPPLICABLE): /takeByte>#(Int(100).R|kotlin/Int.times|(Int(100)))
<Unresolved name: taleByte>#(Int(10).R|kotlin/Int.div|(Int(10)))
@@ -46,8 +46,8 @@ FILE: operatorsOverLiterals.kt
<Inapplicable(INAPPLICABLE): /takeByte>#(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|<local>/inv|())
}
public final fun test_6(): R|kotlin/Unit| {

View File

@@ -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<ft<kotlin/String, kotlin/String?>!>, kotlin/Array<out ft<kotlin/String, kotlin/String?>!>?>!| = 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<ft<kotlin/String, kotlin/String?>!>, kotlin/Array<out ft<kotlin/String, kotlin/String?>!>?>!| = this@R|/A|.R|/Some.bar|(R|kotlin/intArrayOf|(vararg(Int(0), Int(2), Int(-2))))
}
}

View File

@@ -368,13 +368,25 @@ class ExpressionsConverter(
prefix = unaryExpression.tokenType == PREFIX_EXPRESSION
) { getAsFirExpression(this) }
}
val receiver = getAsFirExpression<FirExpression>(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}")

View File

@@ -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}")

View File

@@ -16,14 +16,14 @@ fun test() {
<!INAPPLICABLE_CANDIDATE!>fooInt<!>(p3)
fooInt(p4)
<!INAPPLICABLE_CANDIDATE!>fooInt<!>(p5)
fooInt(p6)
<!INAPPLICABLE_CANDIDATE!>fooInt<!>(p6)
<!INAPPLICABLE_CANDIDATE!>fooLong<!>(p1)
fooLong(p2)
<!INAPPLICABLE_CANDIDATE!>fooLong<!>(p3)
<!INAPPLICABLE_CANDIDATE!>fooLong<!>(p4)
<!INAPPLICABLE_CANDIDATE!>fooLong<!>(p5)
<!INAPPLICABLE_CANDIDATE!>fooLong<!>(p6)
fooLong(p6)
<!INAPPLICABLE_CANDIDATE!>fooShort<!>(p1)
<!INAPPLICABLE_CANDIDATE!>fooShort<!>(p2)
@@ -38,4 +38,4 @@ fun test() {
<!INAPPLICABLE_CANDIDATE!>fooByte<!>(p4)
<!INAPPLICABLE_CANDIDATE!>fooByte<!>(p5)
<!INAPPLICABLE_CANDIDATE!>fooByte<!>(p6)
}
}

View File

@@ -11,8 +11,7 @@ FILE fqName:<root> 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:<get-test2> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [val]
BLOCK_BODY

View File

@@ -79,7 +79,7 @@ fun case_4() {
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Int>(-2147483649)
-2147483649 checkType { <!NONE_APPLICABLE!>check<!><Byte>() }
-2147483649 checkType { <!NONE_APPLICABLE!>check<!><Short>() }
-2147483649 checkType { check<Int>() }
-2147483649 checkType { <!NONE_APPLICABLE!>check<!><Int>() }
}
// TESTCASE NUMBER: 5
@@ -96,7 +96,7 @@ fun case_5() {
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Int>(-9223372036854775807)
-9223372036854775807 checkType { <!NONE_APPLICABLE!>check<!><Byte>() }
-9223372036854775807 checkType { <!NONE_APPLICABLE!>check<!><Short>() }
-9223372036854775807 checkType { check<Int>() }
-9223372036854775807 checkType { <!NONE_APPLICABLE!>check<!><Int>() }
}
// TESTCASE NUMBER: 6

View File

@@ -68,7 +68,7 @@ fun case_4() {
checkSubtype<Int>(-2147483648)
checkSubtype<Long>(-2147483648)
-2147483649 checkType { <!NONE_APPLICABLE!>check<!><Long>() }
-2147483649 checkType { check<Long>() }
checkSubtype<Long>(-2147483649)
}
@@ -77,6 +77,6 @@ fun case_5() {
9223372036854775807 checkType { check<Long>() }
checkSubtype<Long>(9223372036854775807)
-9223372036854775807 checkType { <!NONE_APPLICABLE!>check<!><Long>() }
-9223372036854775807 checkType { check<Long>() }
checkSubtype<Long>(-9223372036854775807)
}

View File

@@ -68,7 +68,7 @@ fun case_4() {
checkSubtype<Int>(-0x80000000)
checkSubtype<Long>(-0x80000000)
-0x80000001 checkType { <!NONE_APPLICABLE!>check<!><Long>() }
-0x80000001 checkType { check<Long>() }
checkSubtype<Long>(-0x80000001)
}
@@ -77,6 +77,6 @@ fun case_5() {
0X7FFFFFFFFFFFFFFF checkType { check<Long>() }
checkSubtype<Long>(0X7FFFFFFFFFFFFFFF)
-0X7FFFFFFFFFFFFFFF checkType { <!NONE_APPLICABLE!>check<!><Long>() }
-0X7FFFFFFFFFFFFFFF checkType { check<Long>() }
checkSubtype<Long>(-0X7FFFFFFFFFFFFFFF)
}

View File

@@ -68,7 +68,7 @@ fun case_4() {
checkSubtype<Int>(-0B10000000000000000000000000000000)
checkSubtype<Long>(-0B10000000000000000000000000000000)
-0b10000000000000000000000000000001 checkType { <!NONE_APPLICABLE!>check<!><Long>() }
-0b10000000000000000000000000000001 checkType { check<Long>() }
checkSubtype<Long>(-0b10000000000000000000000000000001)
}
@@ -77,6 +77,6 @@ fun case_5() {
0b111111111111111111111111111111111111111111111111111111111111111 checkType { check<Long>() }
checkSubtype<Long>(0b111111111111111111111111111111111111111111111111111111111111111)
-0B111111111111111111111111111111111111111111111111111111111111111 checkType { <!NONE_APPLICABLE!>check<!><Long>() }
-0B111111111111111111111111111111111111111111111111111111111111111 checkType { check<Long>() }
checkSubtype<Long>(-0B111111111111111111111111111111111111111111111111111111111111111)
}