[FIR] Desugar increment/decrement in body resolve phase

The expression needs to be resolved first to determine if there is a
receiver that needs to be extracted to a temporary variable. Also, the
special case for prefix increment/decrement on local variable without
delegates requires resolution to check if the variable is local.

^KT-56771 Fixed
^KT-56659 Fixed
This commit is contained in:
Kirill Rakhman
2023-02-21 16:24:34 +01:00
committed by Space Team
parent 5ecf9cce25
commit 3b9724d20e
77 changed files with 1171 additions and 553 deletions
@@ -1,6 +1,9 @@
while(CMP(<, R|<local>/x|.R|kotlin/Int.compareTo|(Int(2)))) {
[BODY_RESOLVE] lval <unary>: R|kotlin/Int| = R|<local>/x|
R|<local>/x| = R|<local>/<unary>|.R|kotlin/Int.dec|()
R|<local>/<unary>|
{
[BODY_RESOLVE] lval <unary>: R|kotlin/Int| = R|<local>/x|
R|<local>/x| = R|<local>/<unary>|.R|kotlin/Int.dec|()
R|<local>/<unary>|
}
[BODY_RESOLVE] lval z: R|kotlin/Int| = R|<local>/y|
}
@@ -357,6 +357,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/IncorrectCharacterLiterals.kt");
}
@Test
@TestMetadata("incrementDecrementOnFullyQualified.kt")
public void testIncrementDecrementOnFullyQualified() throws Exception {
runTest("compiler/testData/diagnostics/tests/incrementDecrementOnFullyQualified.kt");
}
@Test
@TestMetadata("incrementDecrementOnObject.kt")
public void testIncrementDecrementOnObject() throws Exception {
runTest("compiler/testData/diagnostics/tests/incrementDecrementOnObject.kt");
}
@Test
@TestMetadata("InferNullabilityInThenBlock.kt")
public void testInferNullabilityInThenBlock() throws Exception {
@@ -81,9 +81,12 @@ FILE: CanBeValChecker.kt
when () {
R|<local>/flag| -> {
while(CMP(>, R|<local>/a|.R|kotlin/Int.compareTo|(Int(0)))) {
lval <unary>: R|kotlin/Int| = R|<local>/a|
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.dec|()
R|<local>/<unary>|
{
lval <unary>: R|kotlin/Int| = R|<local>/a|
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.dec|()
R|<local>/<unary>|
}
}
}
@@ -111,17 +114,23 @@ FILE: CanBeValChecker.kt
lvar v2: R|kotlin/Int| = Int(2)
lvar v3: R|kotlin/Int| = Int(3)
R|<local>/v1| = Int(1)
lval <unary>: R|kotlin/Int| = R|<local>/v2|
R|<local>/v2| = R|<local>/<unary>|.R|kotlin/Int.inc|()
R|<local>/<unary>|
{
lval <unary>: R|kotlin/Int| = R|<local>/v2|
R|<local>/v2| = R|<local>/<unary>|.R|kotlin/Int.inc|()
R|<local>/<unary>|
}
R|kotlin/io/print|(R|<local>/v3|)
}
public final fun test(): R|kotlin/Unit| {
lvar a: R|kotlin/Int| = Int(0)
while(CMP(>, R|<local>/a|.R|kotlin/Int.compareTo|(Int(0)))) {
lval <unary>: R|kotlin/Int| = R|<local>/a|
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.inc|()
R|<local>/<unary>|
{
lval <unary>: R|kotlin/Int| = R|<local>/a|
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.inc|()
R|<local>/<unary>|
}
}
}
@@ -143,16 +152,22 @@ FILE: CanBeValChecker.kt
public final fun cycles(): R|kotlin/Unit| {
lvar a: R|kotlin/Int| = Int(10)
while(CMP(>, R|<local>/a|.R|kotlin/Int.compareTo|(Int(0)))) {
lval <unary>: R|kotlin/Int| = R|<local>/a|
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.dec|()
R|<local>/<unary>|
{
lval <unary>: R|kotlin/Int| = R|<local>/a|
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.dec|()
R|<local>/<unary>|
}
}
lvar b: R|kotlin/Int|
while(CMP(<, R|<local>/a|.R|kotlin/Int.compareTo|(Int(10)))) {
lval <unary>: R|kotlin/Int| = R|<local>/a|
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.inc|()
R|<local>/<unary>|
{
lval <unary>: R|kotlin/Int| = R|<local>/a|
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.inc|()
R|<local>/<unary>|
}
R|<local>/b| = R|<local>/a|
}
@@ -357,6 +357,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/IncorrectCharacterLiterals.kt");
}
@Test
@TestMetadata("incrementDecrementOnFullyQualified.kt")
public void testIncrementDecrementOnFullyQualified() throws Exception {
runTest("compiler/testData/diagnostics/tests/incrementDecrementOnFullyQualified.kt");
}
@Test
@TestMetadata("incrementDecrementOnObject.kt")
public void testIncrementDecrementOnObject() throws Exception {
runTest("compiler/testData/diagnostics/tests/incrementDecrementOnObject.kt");
}
@Test
@TestMetadata("InferNullabilityInThenBlock.kt")
public void testInferNullabilityInThenBlock() throws Exception {
@@ -357,6 +357,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/IncorrectCharacterLiterals.kt");
}
@Test
@TestMetadata("incrementDecrementOnFullyQualified.kt")
public void testIncrementDecrementOnFullyQualified() throws Exception {
runTest("compiler/testData/diagnostics/tests/incrementDecrementOnFullyQualified.kt");
}
@Test
@TestMetadata("incrementDecrementOnObject.kt")
public void testIncrementDecrementOnObject() throws Exception {
runTest("compiler/testData/diagnostics/tests/incrementDecrementOnObject.kt");
}
@Test
@TestMetadata("InferNullabilityInThenBlock.kt")
public void testInferNullabilityInThenBlock() throws Exception {
@@ -469,7 +469,7 @@ fun checkTypeMismatch(
context
)
}
source.kind is KtFakeSourceElementKind.DesugaredIncrementOrDecrement -> {
source.kind is KtFakeSourceElementKind.DesugaredIncrementOrDecrement || assignment?.source?.kind is KtFakeSourceElementKind.DesugaredIncrementOrDecrement -> {
if (!lValueType.isNullable && rValueType.isNullable) {
val tempType = rValueType
rValueType = lValueType
@@ -26873,6 +26873,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -49043,12 +49049,24 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -26873,6 +26873,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -49043,12 +49049,24 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -27,9 +27,7 @@ FILE: destructuring.kt
lvar x: <implicit> = R|<local>/<destruct>|.component1#()
lvar y: <implicit> = R|<local>/<destruct>|.component2#()
lvar z: String = R|<local>/<destruct>|.component3#()
lval <unary>: <implicit> = x#
x# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
x#++
*=(y#, Double(2.0))
z# = String()
}
@@ -1,23 +1,8 @@
FILE: safeCallsWithUnaryOperators.kt
public? final? fun foo(): R|kotlin/Unit| {
a#?.{ {
lval <receiver>: <implicit> = $subj$
lval <unary>: <implicit> = R|<local>/<receiver>|.b#
R|<local>/<receiver>|.b# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
}
}
a#?.{ $subj$.b# }?.{ {
lval <receiver>: <implicit> = $subj$
lval <unary>: <implicit> = R|<local>/<receiver>|.c#
R|<local>/<receiver>|.c# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
}
}
lval <receiver>: <implicit> = a#?.{ $subj$.b# }
lval <unary>: <implicit> = R|<local>/<receiver>|.c#
R|<local>/<receiver>|.c# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
a#?.{ $subj$.b# }++
a#?.{ $subj$.b# }?.{ $subj$.c# }++
a#?.{ $subj$.b# }.c#++
a#?.{ {
lval <array>: <implicit> = $subj$.b#
lval <index_0>: <implicit> = IntegerLiteral(0)
@@ -60,30 +45,12 @@ FILE: safeCallsWithUnaryOperators.kt
lval <unary>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|)
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary>|.inc#())
R|<local>/<unary>|
lval <receiver>: <implicit> = a#?.{ $subj$.b# }
lval <unary>: <implicit> = R|<local>/<receiver>|.d#()
R|<local>/<receiver>|.d#() = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
a#?.{ $subj$.b# }.d#()++
}
public? final? fun foo2(): R|kotlin/Unit| {
a#?.{ {
lval <receiver>: <implicit> = $subj$
lval <unary-result>: <implicit> = R|<local>/<receiver>|.b#.inc#()
R|<local>/<receiver>|.b# = R|<local>/<unary-result>|
R|<local>/<unary-result>|
}
}
a#?.{ $subj$.b# }?.{ {
lval <receiver>: <implicit> = $subj$
lval <unary-result>: <implicit> = R|<local>/<receiver>|.c#.inc#()
R|<local>/<receiver>|.c# = R|<local>/<unary-result>|
R|<local>/<unary-result>|
}
}
lval <receiver>: <implicit> = a#?.{ $subj$.b# }
lval <unary-result>: <implicit> = R|<local>/<receiver>|.c#.inc#()
R|<local>/<receiver>|.c# = R|<local>/<unary-result>|
R|<local>/<unary-result>|
++a#?.{ $subj$.b# }
++a#?.{ $subj$.b# }?.{ $subj$.c# }
++a#?.{ $subj$.b# }.c#
a#?.{ {
lval <array>: <implicit> = $subj$.b#
lval <index_0>: <implicit> = IntegerLiteral(0)
@@ -126,8 +93,5 @@ FILE: safeCallsWithUnaryOperators.kt
lval <unary-result>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#()
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary-result>|)
R|<local>/<unary-result>|
lval <receiver>: <implicit> = a#?.{ $subj$.b# }
lval <unary-result>: <implicit> = R|<local>/<receiver>|.d#().inc#()
R|<local>/<receiver>|.d#() = R|<local>/<unary-result>|
R|<local>/<unary-result>|
++a#?.{ $subj$.b# }.d#()
}
@@ -1,28 +1,10 @@
FILE: unary.kt
public? final? fun test(): R|kotlin/Unit| {
lvar x: <implicit> = IntegerLiteral(0)
lval x1: <implicit> = {
lval <unary>: <implicit> = x#
x# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
}
lval x2: <implicit> = {
x# = x#.inc#()
x#
}
lval x3: <implicit> = {
x# = x#.dec#()
x#
}
lval x4: <implicit> = {
lval <unary>: <implicit> = x#
x# = R|<local>/<unary>|.dec#()
R|<local>/<unary>|
}
lval x1: <implicit> = x#++
lval x2: <implicit> = ++x#
lval x3: <implicit> = --x#
lval x4: <implicit> = x#--
when () {
==(x#, IntegerLiteral(0)).not#() -> {
println#(String(000))
@@ -40,20 +22,8 @@ FILE: unary.kt
}
public? final? fun test2(x: X): R|kotlin/Unit| {
lval x1: <implicit> = {
lval <receiver>: <implicit> = x#
lval <unary>: <implicit> = R|<local>/<receiver>|.i#
R|<local>/<receiver>|.i# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
}
lval x2: <implicit> = {
lval <receiver>: <implicit> = x#
lval <unary-result>: <implicit> = R|<local>/<receiver>|.i#.inc#()
R|<local>/<receiver>|.i# = R|<local>/<unary-result>|
R|<local>/<unary-result>|
}
lval x1: <implicit> = x#.i#++
lval x2: <implicit> = ++x#.i#
}
public? final? fun test3(arr: Array<Int>): R|kotlin/Unit| {
lval x1: <implicit> = {
@@ -2,14 +2,10 @@ FILE: while.kt
public? final? fun foo(limit: Int): R|kotlin/Unit| {
lvar k: <implicit> = IntegerLiteral(0)
some@while(CMP(<, k#.compareTo#(limit#))) {
lval <unary>: <implicit> = k#
k# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
k#++
println#(k#)
while(==(k#, IntegerLiteral(13))) {
lval <unary>: <implicit> = k#
k# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
k#++
when () {
CMP(<, k#.compareTo#(limit#)) -> {
break@@@[CMP(<, k#.compareTo#(limit#))]
@@ -30,9 +26,7 @@ FILE: while.kt
public? final? fun bar(limit: Int): R|kotlin/Unit| {
lvar k: <implicit> = limit#
do {
lval <unary>: <implicit> = k#
k# = R|<local>/<unary>|.dec#()
R|<local>/<unary>|
k#--
println#(k#)
}
while(CMP(>=, k#.compareTo#(IntegerLiteral(0))))
@@ -510,17 +510,6 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
diagnostic = ConeSimpleDiagnostic("Inc/dec without operand", DiagnosticKind.Syntax)
}
if (unwrappedReceiver.elementType == DOT_QUALIFIED_EXPRESSION || unwrappedReceiver.elementType == SAFE_ACCESS_EXPRESSION) {
return generateIncrementOrDecrementBlockForQualifiedAccess(
wholeExpression,
operationReference,
unwrappedReceiver,
callName,
prefix,
convert
)
}
if (unwrappedReceiver.elementType == ARRAY_ACCESS_EXPRESSION) {
return generateIncrementOrDecrementBlockForArrayAccess(
wholeExpression,
@@ -532,43 +521,13 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
)
}
return buildBlock {
return buildIncrementDecrementExpression {
val baseSource = wholeExpression?.toFirSourceElement()
val desugaredSource = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
source = desugaredSource
val convertedReceiver = unwrappedReceiver.convert()
putIncrementOrDecrementStatements(
convertedReceiver,
operationReference,
callName,
prefix,
unwrappedReceiver.takeIf { it.elementType == REFERENCE_EXPRESSION }?.getReferencedNameAsName(),
desugaredSource,
) { resultInitializer: FirExpression, resultVar: FirVariable ->
val assignment = unwrappedReceiver.generateAssignment(
desugaredSource,
null,
if (prefix && unwrappedReceiver.elementType != REFERENCE_EXPRESSION)
generateResolvedAccessExpression(source, resultVar)
else
resultInitializer,
FirOperation.ASSIGN,
resultInitializer.annotations,
null
) {
// We want the DesugaredAssignmentValueReferenceExpression on the LHS to point to the same receiver instance
// as in the initializer, therefore don't create a new instance here if the argument is the receiver.
if (this == unwrappedReceiver) convertedReceiver else convert()
}
if (assignment is FirBlock) {
statements += assignment.statements
} else {
statements += assignment
}
}
source = baseSource
operationSource = operationReference?.toFirSourceElement()
operationName = callName
isPrefix = prefix
expression = unwrappedReceiver.convert()
}
}
@@ -672,86 +631,6 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
}
/**
* given:
* a.b++
*
* result:
* {
* val <receiver> = a
* val <unary> = <receiver>.b
* <receiver>.b = <unary>.inc()
* ^<unary>
* }
*
* given:
* ++a.b
*
* result:
* {
* val <receiver> = a
* val <unary-result> = <receiver>.b.inc()
* <receiver>.b = <unary-result>
* ^<unary-result>
* }
*
*/
@OptIn(FirContractViolation::class)
private fun generateIncrementOrDecrementBlockForQualifiedAccess(
wholeExpression: T,
operationReference: T?,
receiverForOperation: T, // a.b
callName: Name,
prefix: Boolean,
convert: T.() -> FirExpression
): FirExpression {
return buildBlockProbablyUnderSafeCall(
receiverForOperation,
convert,
receiverForOperation.toFirSourceElement(),
) { qualifiedFir ->
val receiverFir = (qualifiedFir as? FirQualifiedAccessExpression)?.explicitReceiver ?: buildErrorExpression {
source = receiverForOperation.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Qualified expression without selector", DiagnosticKind.Syntax)
}
val baseSource = wholeExpression?.toFirSourceElement()
val desugaredSource = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
source = desugaredSource
val argumentReceiverVariable = generateTemporaryVariable(
baseModuleData,
desugaredSource,
SpecialNames.RECEIVER,
initializer = receiverFir,
).also { statements += it }
val receiverSource = receiverFir.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
val firArgument = generateResolvedAccessExpression(receiverSource, argumentReceiverVariable).let { receiver ->
qualifiedFir.also { if (it is FirQualifiedAccessExpression) it.replaceExplicitReceiver(receiver) }
}
putIncrementOrDecrementStatements(
firArgument, operationReference, callName, prefix,
nameIfSimpleReference = null, desugaredSource
) { resultInitializer: FirExpression, resultVar: FirVariable ->
if (firArgument !is FirQualifiedAccessExpression) return@putIncrementOrDecrementStatements
statements += buildVariableAssignment {
source = desugaredSource
lValue = buildDesugaredAssignmentValueReferenceExpression {
expressionRef = FirExpressionRef<FirExpression>().apply { bind(firArgument) }
source = firArgument.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
}
rValue = if (prefix) {
generateResolvedAccessExpression(source, resultVar)
} else {
resultInitializer
}
}
}
}
}
/**
* given:
* a[b, c]++
@@ -160,6 +160,13 @@ abstract class FirAbstractBodyResolveTransformerDispatcher(
return expressionsTransformer.transformAssignmentOperatorStatement(assignmentOperatorStatement, data)
}
override fun transformIncrementDecrementExpression(
incrementDecrementExpression: FirIncrementDecrementExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformIncrementDecrementExpression(incrementDecrementExpression, data)
}
override fun transformEqualityOperatorCall(
equalityOperatorCall: FirEqualityOperatorCall,
data: ResolutionMode
@@ -21,13 +21,10 @@ import org.jetbrains.kotlin.fir.extensions.assignAltererExtensions
import org.jetbrains.kotlin.fir.extensions.expressionResolutionExtensions
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.references.builder.*
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.expressions.unwrapSmartcastExpression
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.inference.FirStubInferenceSession
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
@@ -678,6 +675,124 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
}
@OptIn(FirContractViolation::class)
override fun transformIncrementDecrementExpression(
incrementDecrementExpression: FirIncrementDecrementExpression,
data: ResolutionMode
): FirStatement {
incrementDecrementExpression.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
val originalExpression = incrementDecrementExpression.expression.transformSingle(transformer, ResolutionMode.ContextIndependent)
val expression = when (originalExpression) {
is FirSafeCallExpression -> originalExpression.selector as? FirExpression ?: buildErrorExpression {
source = originalExpression.source
diagnostic = ConeSimpleDiagnostic("Safe call selector expected to be an expression here", DiagnosticKind.Syntax)
}
else -> originalExpression
}
val desugaredSource = incrementDecrementExpression.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
fun generateTemporaryVariable(name: Name, initializer: FirExpression): FirProperty = generateTemporaryVariable(
moduleData = session.moduleData,
source = desugaredSource,
name = name,
initializer = initializer,
typeRef = initializer.typeRef.copyWithNewSource(desugaredSource),
)
fun buildAndResolveOperatorCall(receiver: FirExpression): FirFunctionCall = buildFunctionCall {
source = incrementDecrementExpression.operationSource
explicitReceiver = receiver
calleeReference = buildSimpleNamedReference {
val referenceSourceKind = when {
incrementDecrementExpression.isPrefix -> KtFakeSourceElementKind.DesugaredPrefixNameReference
else -> KtFakeSourceElementKind.DesugaredPostfixNameReference
}
source = incrementDecrementExpression.operationSource?.fakeElement(referenceSourceKind)
name = incrementDecrementExpression.operationName
}
origin = FirFunctionCallOrigin.Operator
}.transformSingle(transformer, ResolutionMode.ContextIndependent)
fun buildAndResolveVariableAssignment(rValue: FirExpression): FirVariableAssignment = buildVariableAssignment {
source = desugaredSource
lValue = buildDesugaredAssignmentValueReferenceExpression {
source = ((expression as? FirErrorExpression)?.expression ?: expression).source
?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
expressionRef = FirExpressionRef<FirExpression>().apply { bind(expression.unwrapSmartcastExpression()) }
}
this.rValue = rValue
}.transformSingle(transformer, ResolutionMode.ContextIndependent)
val block = buildBlock {
source = desugaredSource
annotations += incrementDecrementExpression.annotations
(expression as? FirQualifiedAccessExpression)?.explicitReceiver
// If a receiver x exists, write it to a temporary variable to prevent multiple calls to it.
// Exceptions: ResolvedQualifiers and ThisReceivers as they can't have side effects when called.
?.takeIf { it is FirQualifiedAccessExpression && it !is FirThisReceiverExpression }
?.let { receiver ->
// val <receiver> = x
statements += generateTemporaryVariable(SpecialNames.RECEIVER, receiver).also { property ->
// Change the expression from x.a to <receiver>.a
val newReceiverAccess =
property.toQualifiedAccess(fakeSource = receiver.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement))
if (expression.explicitReceiver == expression.dispatchReceiver) {
expression.replaceDispatchReceiver(newReceiverAccess)
} else {
expression.replaceExtensionReceiver(newReceiverAccess)
}
expression.replaceExplicitReceiver(newReceiverAccess)
}
}
if (incrementDecrementExpression.isPrefix) {
val targetProperty = expression.calleeReference?.toResolvedPropertySymbol()?.fir
val operatorCall = buildAndResolveOperatorCall(expression)
// Special case for prefix inc/dec on local variable without delegate where unary-result variable generation is skipped.
if (targetProperty?.isLocal == true && targetProperty.delegate == null) {
// a = a.inc()
statements += buildAndResolveVariableAssignment(operatorCall)
// ^a
statements += targetProperty.toQualifiedAccess(fakeSource = desugaredSource, typeRef = noExpectedType)
// If inc() returns a subtype of its receiver type, the variable access should be smart-casted.
.transform<FirStatement, ResolutionMode>(transformer, withExpectedType(operatorCall.typeRef.coneType))
} else {
val unaryResultVariable = generateTemporaryVariable(SpecialNames.UNARY_RESULT, operatorCall)
// val <unary-result> = a.inc()
statements += unaryResultVariable
// a = <unary-result>
statements += buildAndResolveVariableAssignment(unaryResultVariable.toQualifiedAccess(fakeSource = desugaredSource))
// ^<unary-result>
statements += unaryResultVariable.toQualifiedAccess(fakeSource = desugaredSource)
}
} else {
val unaryVariable = generateTemporaryVariable(SpecialNames.UNARY, expression)
// val <unary> = a
statements += unaryVariable
// a = <unary>.inc()
statements += buildAndResolveVariableAssignment(buildAndResolveOperatorCall(unaryVariable.toQualifiedAccess()))
// ^<unary>
statements += unaryVariable.toQualifiedAccess()
}
}.apply {
replaceTypeRef((statements.last() as FirExpression).typeRef.copyWithNewSource(null))
}
return if (originalExpression is FirSafeCallExpression) {
originalExpression.replaceSelector(block)
originalExpression
} else {
block
}
}
override fun transformEqualityOperatorCall(
equalityOperatorCall: FirEqualityOperatorCall,
data: ResolutionMode
@@ -891,14 +1006,6 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
): FirStatement = whileAnalysing(session, variableAssignment) {
variableAssignment.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
val isDesugaredIncrementDecrement = variableAssignment.source?.kind == KtFakeSourceElementKind.DesugaredIncrementOrDecrement
// Expressions like `++a` are desugared into `a = a.inc()` where the LHS is a FirDesugaredAssignmentValueReferenceExpression
// that's pointing to the not yet resolved `a` on the RHS. For the resolution to work, the RHS must therefore be resolved first.
if (isDesugaredIncrementDecrement) {
variableAssignment.transformRValue(transformer, ResolutionMode.ContextIndependent)
}
variableAssignment.transformLValue(transformer, ResolutionMode.AssignmentLValue(variableAssignment))
val resolvedReference = variableAssignment.calleeReference
@@ -926,14 +1033,10 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
}
val result = if (!isDesugaredIncrementDecrement) {
variableAssignment.transformRValue(
transformer,
withExpectedType(variableAssignment.lValue.typeRef, expectedTypeMismatchIsReportedInChecker = true),
)
} else {
variableAssignment
}
val result = variableAssignment.transformRValue(
transformer,
withExpectedType(variableAssignment.lValue.typeRef, expectedTypeMismatchIsReportedInChecker = true),
)
(result as? FirVariableAssignment)?.let { dataFlowAnalyzer.exitVariableAssignment(it) }
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class FirIncrementDecrementExpression : FirExpression() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation>
abstract val isPrefix: Boolean
abstract val operationName: Name
abstract val expression: FirExpression
abstract val operationSource: KtSourceElement?
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitIncrementDecrementExpression(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformIncrementDecrementExpression(this, data) as E
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirIncrementDecrementExpression
}
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.builder
import kotlin.contracts.*
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirIncrementDecrementExpressionImpl
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.name.Name
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
@FirBuilderDsl
class FirIncrementDecrementExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override val annotations: MutableList<FirAnnotation> = mutableListOf()
var isPrefix: Boolean by kotlin.properties.Delegates.notNull<Boolean>()
lateinit var operationName: Name
lateinit var expression: FirExpression
var operationSource: KtSourceElement? = null
override fun build(): FirIncrementDecrementExpression {
return FirIncrementDecrementExpressionImpl(
source,
annotations.toMutableOrEmpty(),
isPrefix,
operationName,
expression,
operationSource,
)
}
@Deprecated("Modification of 'typeRef' has no impact for FirIncrementDecrementExpressionBuilder", level = DeprecationLevel.HIDDEN)
override var typeRef: FirTypeRef
get() = throw IllegalStateException()
set(_) {
throw IllegalStateException()
}
}
@OptIn(ExperimentalContracts::class)
inline fun buildIncrementDecrementExpression(init: FirIncrementDecrementExpressionBuilder.() -> Unit): FirIncrementDecrementExpression {
contract {
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
}
return FirIncrementDecrementExpressionBuilder().apply(init).build()
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.impl
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.fir.MutableOrEmptyList
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
internal class FirIncrementDecrementExpressionImpl(
override val source: KtSourceElement?,
override var annotations: MutableOrEmptyList<FirAnnotation>,
override val isPrefix: Boolean,
override val operationName: Name,
override var expression: FirExpression,
override val operationSource: KtSourceElement?,
) : FirIncrementDecrementExpression() {
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
typeRef.accept(visitor, data)
annotations.forEach { it.accept(visitor, data) }
expression.accept(visitor, data)
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirIncrementDecrementExpressionImpl {
typeRef = typeRef.transform(transformer, data)
transformAnnotations(transformer, data)
expression = expression.transform(transformer, data)
return this
}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirIncrementDecrementExpressionImpl {
annotations.transformInplace(transformer, data)
return this
}
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
typeRef = newTypeRef
}
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) {
annotations = newAnnotations.toMutableOrEmpty()
}
}
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -214,6 +215,8 @@ abstract class FirDefaultVisitor<out R, in D> : FirVisitor<R, D>() {
override fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement, data: D): R = visitStatement(assignmentOperatorStatement, data)
override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: D): R = visitExpression(incrementDecrementExpression, data)
override fun visitAugmentedArraySetCall(augmentedArraySetCall: FirAugmentedArraySetCall, data: D): R = visitStatement(augmentedArraySetCall, data)
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: D): R = visitExpression(classReferenceExpression, data)
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -214,6 +215,8 @@ abstract class FirDefaultVisitorVoid : FirVisitorVoid() {
override fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement) = visitStatement(assignmentOperatorStatement)
override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression) = visitExpression(incrementDecrementExpression)
override fun visitAugmentedArraySetCall(augmentedArraySetCall: FirAugmentedArraySetCall) = visitStatement(augmentedArraySetCall)
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression) = visitExpression(classReferenceExpression)
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -463,6 +464,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformElement(assignmentOperatorStatement, data)
}
open fun transformIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: D): FirStatement {
return transformElement(incrementDecrementExpression, data)
}
open fun transformEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: D): FirStatement {
return transformElement(equalityOperatorCall, data)
}
@@ -1039,6 +1044,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformAssignmentOperatorStatement(assignmentOperatorStatement, data)
}
final override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: D): FirStatement {
return transformIncrementDecrementExpression(incrementDecrementExpression, data)
}
final override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: D): FirStatement {
return transformEqualityOperatorCall(equalityOperatorCall, data)
}
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -310,6 +311,8 @@ abstract class FirVisitor<out R, in D> {
open fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement, data: D): R = visitElement(assignmentOperatorStatement, data)
open fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: D): R = visitElement(incrementDecrementExpression, data)
open fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: D): R = visitElement(equalityOperatorCall, data)
open fun visitWhenExpression(whenExpression: FirWhenExpression, data: D): R = visitElement(whenExpression, data)
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -462,6 +463,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitElement(assignmentOperatorStatement)
}
open fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression) {
visitElement(incrementDecrementExpression)
}
open fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall) {
visitElement(equalityOperatorCall)
}
@@ -1038,6 +1043,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitAssignmentOperatorStatement(assignmentOperatorStatement)
}
final override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: Nothing?) {
visitIncrementDecrementExpression(incrementDecrementExpression)
}
final override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Nothing?) {
visitEqualityOperatorCall(equalityOperatorCall)
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fakeElement
@@ -14,7 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
@@ -25,15 +26,17 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.name.Name
fun FirVariable.toQualifiedAccess(): FirQualifiedAccessExpression = buildPropertyAccessExpression {
val fakeSource = this@toQualifiedAccess.source?.fakeElement(KtFakeSourceElementKind.ReferenceInAtomicQualifiedAccess)
fun FirVariable.toQualifiedAccess(
fakeSource: KtSourceElement? = source?.fakeElement(KtFakeSourceElementKind.ReferenceInAtomicQualifiedAccess),
typeRef: FirTypeRef = returnTypeRef
): FirQualifiedAccessExpression = buildPropertyAccessExpression {
source = fakeSource
calleeReference = buildResolvedNamedReference {
source = fakeSource
name = this@toQualifiedAccess.name
resolvedSymbol = this@toQualifiedAccess.symbol
}
typeRef = this@toQualifiedAccess.returnTypeRef
this.typeRef = typeRef
}
fun generateTemporaryVariable(
@@ -42,7 +45,7 @@ fun generateTemporaryVariable(
name: Name,
initializer: FirExpression,
typeRef: FirTypeRef? = null,
extractedAnnotations: Collection<FirAnnotation>? = null,
extractedAnnotations: Collection<FirAnnotation>? = null
): FirProperty =
buildProperty {
this.source = source
@@ -56,7 +59,7 @@ fun generateTemporaryVariable(
symbol = FirPropertySymbol(name)
isVar = false
isLocal = true
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
status = FirResolvedDeclarationStatusImpl(Visibilities.Local, Modality.FINAL, EffectiveVisibility.Local)
if (extractedAnnotations != null) {
// LT extracts annotations ahead.
// PSI extracts annotations on demand. Use a similar util in [PsiConversionUtils]
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
class FirRenderer(
@@ -1022,6 +1023,14 @@ class FirRenderer(
print(")")
}
override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression) {
annotationRenderer?.render(incrementDecrementExpression)
val operator = if (incrementDecrementExpression.operationName == OperatorNameConventions.INC) "++" else "--"
if (incrementDecrementExpression.isPrefix) print(operator)
incrementDecrementExpression.expression.accept(visitor)
if (!incrementDecrementExpression.isPrefix) print(operator)
}
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall) {
annotationRenderer?.render(equalityOperatorCall)
print(equalityOperatorCall.operation.operator)
@@ -104,6 +104,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val comparisonExpression by element(Expression, expression)
val typeOperatorCall by element(Expression, expression, call)
val assignmentOperatorStatement by element(Expression, statement)
val incrementDecrementExpression by element(Expression, expression)
val equalityOperatorCall by element(Expression, expression, call)
val whenExpression by element(Expression, expression, resolvable)
val whenBranch by element(Expression)
@@ -317,6 +317,8 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(assignmentOperatorStatement)
impl(incrementDecrementExpression)
impl(equalityOperatorCall) {
default("typeRef", "FirImplicitBooleanTypeRef(null)")
useTypes(implicitBooleanTypeRefType)
@@ -254,6 +254,13 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("rightArgument", expression).withTransform()
}
incrementDecrementExpression.configure {
+booleanField("isPrefix")
+field("operationName", nameType)
+field("expression", expression)
+field("operationSource", sourceElementType, nullable = true)
}
equalityOperatorCall.configure {
+field("operation", operationType)
}
+4 -1
View File
@@ -1,3 +1,6 @@
// IGNORE_BACKEND_K2: ANY
// Behavior changed in K2, see KT-42077
public var inc: Int = 0
public var propInc: Int = 0
@@ -26,4 +29,4 @@ fun box(): String {
if (propDec != -1) return "fail in prefix decrement: ${propDec} != -1"
return "OK"
}
}
@@ -0,0 +1,34 @@
// IGNORE_BACKEND_K1: ANY
// Behavior changed in K2, see KT-42077
// IGNORE_BACKEND: WASM
// SKIP_NODE_JS
public var inc: Int = 0
public var propInc: Int = 0
get() {++inc; return field}
set(a: Int) {
++inc
field = a
}
public var dec: Int = 0
public var propDec: Int = 0
get() { --dec; return field}
set(a: Int) {
--dec
field = a
}
fun box(): String {
++propInc
if (inc != 2) return "fail in prefix increment: ${inc} != 2"
if (propInc != 1) return "fail in prefix increment: ${propInc} != 1"
--propDec
if (dec != -2) return "fail in prefix decrement: ${dec} != -2"
if (propDec != -1) return "fail in prefix decrement: ${propDec} != -1"
return "OK"
}
+4 -1
View File
@@ -1,3 +1,6 @@
// IGNORE_BACKEND_K2: ANY
// Behavior changed in K2, see KT-42077
class A {
companion object {
private var r: Int = 1;
@@ -70,4 +73,4 @@ fun box() : String {
if (p4 != 3 || A.holder != "getR4setR4:getR4setR4getR4getR4") return "fail 4: $p4 ${A.holder}"
return "OK"
}
}
@@ -0,0 +1,78 @@
// IGNORE_BACKEND_K1: ANY
// Behavior changed in K2, see KT-42077
// IGNORE_BACKEND: WASM
// SKIP_NODE_JS
class A {
companion object {
private var r: Int = 1;
fun test(): Int {
r++
++r
return r
}
var holder: String = ""
var r2: Int = 1
get() {
holder += "getR2"
return field
}
fun test2() : Int {
r2++
++r2
return r2
}
var r3: Int = 1
set(p: Int) {
holder += "setR3"
field = p
}
fun test3() : Int {
r3++
++r3
return r3
}
var r4: Int = 1
get() {
holder += "getR4"
return field
}
set(p: Int) {
holder += "setR4"
field = p
}
fun test4() : Int {
r4++
holder += ":"
++r4
return r4
}
}
}
fun box() : String {
val p = A.test()
if (p != 3) return "fail 1: $p"
val p2 = A.test2()
var holderValue = A.holder
if (p2 != 3 || holderValue != "getR2getR2getR2") return "fail 2: $p2 ${holderValue}"
A.holder = ""
val p3 = A.test3()
if (p3 != 3 || A.holder != "setR3setR3") return "fail 3: $p3 ${A.holder}"
A.holder = ""
val p4 = A.test4()
if (p4 != 3 || A.holder != "getR4setR4:getR4setR4getR4") return "fail 4: $p4 ${A.holder}"
return "OK"
}
+4 -1
View File
@@ -1,3 +1,6 @@
// IGNORE_BACKEND_K2: ANY
// Behavior changed in K2, see KT-42077
object A {
private var r: Int = 1;
@@ -68,4 +71,4 @@ fun box() : String {
if (p4 != 3 || A.holder != "getR4setR4:getR4setR4getR4getR4") return "fail 4: $p4 ${A.holder}"
return "OK"
}
}
+76
View File
@@ -0,0 +1,76 @@
// IGNORE_BACKEND_K1: ANY
// Behavior changed in K2, see KT-42077
// IGNORE_BACKEND: WASM
// SKIP_NODE_JS
object A {
private var r: Int = 1;
fun test() : Int {
r++
++r
return r
}
var holder: String = ""
var r2: Int = 1
get() {
holder += "getR2"
return field
}
fun test2() : Int {
r2++
++r2
return r2
}
var r3: Int = 1
set(p: Int) {
holder += "setR3"
field = p
}
fun test3() : Int {
r3++
++r3
return r3
}
var r4: Int = 1
get() {
holder += "getR4"
return field
}
set(p: Int) {
holder += "setR4"
field = p
}
fun test4() : Int {
r4++
holder += ":"
++r4
return r4
}
}
fun box() : String {
val p = A.test()
if (p != 3) return "fail 1: $p"
val p2 = A.test2()
val holderValue = A.holder
if (p2 != 3 || holderValue != "getR2getR2getR2") return "fail 2: $p2 ${holderValue}"
A.holder = ""
val p3 = A.test3()
if (p3 != 3 || A.holder != "setR3setR3") return "fail 3: $p3 ${A.holder}"
A.holder = ""
val p4 = A.test4()
if (p4 != 3 || A.holder != "getR4setR4:getR4setR4getR4") return "fail 4: $p4 ${A.holder}"
return "OK"
}
+4 -4
View File
@@ -22,9 +22,9 @@ class WrongIncDec() {
fun testWrongIncDec() {
var x = WrongIncDec()
<!RESULT_TYPE_MISMATCH!>x++<!>
x<!RESULT_TYPE_MISMATCH!>++<!>
<!RESULT_TYPE_MISMATCH!>++x<!>
<!RESULT_TYPE_MISMATCH!>x--<!>
x<!RESULT_TYPE_MISMATCH!>--<!>
<!RESULT_TYPE_MISMATCH!>--x<!>
}
@@ -41,6 +41,6 @@ fun testUnitIncDec() {
<!INC_DEC_SHOULD_NOT_RETURN_UNIT!>--<!>x
x = x<!INC_DEC_SHOULD_NOT_RETURN_UNIT!>++<!>
x = x<!INC_DEC_SHOULD_NOT_RETURN_UNIT!>--<!>
x = <!INC_DEC_SHOULD_NOT_RETURN_UNIT!>++<!>x
x = <!INC_DEC_SHOULD_NOT_RETURN_UNIT!>--<!>x
x = <!INC_DEC_SHOULD_NOT_RETURN_UNIT, INC_DEC_SHOULD_NOT_RETURN_UNIT!>++<!>x
x = <!INC_DEC_SHOULD_NOT_RETURN_UNIT, INC_DEC_SHOULD_NOT_RETURN_UNIT!>--<!>x
}
@@ -106,7 +106,7 @@ class Test() {
fun testIncompleteSyntax() {
val s = "s"
<!UNRESOLVED_REFERENCE!>++<!>s.<!SYNTAX!><!>
<!UNRESOLVED_REFERENCE!>++<!><!VARIABLE_EXPECTED!>s<!>.<!SYNTAX!><!>
}
fun testVariables() {
@@ -0,0 +1,10 @@
// SKIP_TXT
// FIR_IDENTICAL
package foo.bar
var baz = 1
fun test() {
foo.bar.baz++
}
@@ -0,0 +1,22 @@
// SKIP_TXT
// ISSUE: KT-56659
object AAA { operator fun inc(): AAA = this }
fun test1() {
<!VARIABLE_EXPECTED!>AAA<!>++
}
fun test2() {
++<!VARIABLE_EXPECTED!>AAA<!>
}
fun test3() {
var x = AAA
x = <!VARIABLE_EXPECTED!>AAA<!>++
}
fun test4() {
var x = AAA
x = ++<!VARIABLE_EXPECTED!>AAA<!>
}
@@ -0,0 +1,22 @@
// SKIP_TXT
// ISSUE: KT-56659
object AAA { operator fun inc(): AAA = this }
fun test1() {
<!VAL_REASSIGNMENT!>AAA<!>++
}
fun test2() {
++<!VAL_REASSIGNMENT!>AAA<!>
}
fun test3() {
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = AAA
x = <!VAL_REASSIGNMENT!>AAA<!>++
}
fun test4() {
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = AAA
x = ++<!VAL_REASSIGNMENT!>AAA<!>
}
@@ -1,36 +0,0 @@
// !LANGUAGE: +ForbidExtensionCallsOnInlineFunctionalParameters
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -VAL_REASSIGNMENT -UNUSED_CHANGED_VALUE -VARIABLE_EXPECTED
inline operator fun <T, V> Function1<T, V>.unaryPlus() = this
operator fun <T, V> Function1<T, V>.unaryMinus() = this
inline operator fun <T, V> Function1<T, V>.inc() = this
operator fun <T, V> Function1<T, V>.dec() = this
inline operator fun <T, V> @ExtensionFunctionType Function2<T, T, V>.unaryPlus(){}
operator fun <T, V> @ExtensionFunctionType Function2<T, T, V>.unaryMinus(){}
inline operator fun <T, V> @ExtensionFunctionType Function2<T, T, V>.inc() = this
operator fun <T, V> @ExtensionFunctionType Function2<T, T, V>.dec() = this
inline fun <T, V> inlineFunWithInvoke(s: (p: T) -> V, ext: T.(p: T) -> V) {
+<!USAGE_IS_NOT_INLINABLE!>s<!>
-<!USAGE_IS_NOT_INLINABLE!>s<!>
<!USAGE_IS_NOT_INLINABLE!>s<!>++
<!USAGE_IS_NOT_INLINABLE!>++<!><!USAGE_IS_NOT_INLINABLE!>s<!>
<!USAGE_IS_NOT_INLINABLE!>s<!>--
<!USAGE_IS_NOT_INLINABLE!>--<!><!USAGE_IS_NOT_INLINABLE!>s<!>
+<!USAGE_IS_NOT_INLINABLE!>ext<!>
-<!USAGE_IS_NOT_INLINABLE!>ext<!>
<!USAGE_IS_NOT_INLINABLE!>ext<!>++
<!USAGE_IS_NOT_INLINABLE!>++<!><!USAGE_IS_NOT_INLINABLE!>ext<!>
<!USAGE_IS_NOT_INLINABLE!>ext<!>--
<!USAGE_IS_NOT_INLINABLE!>--<!><!USAGE_IS_NOT_INLINABLE!>ext<!>
}
inline fun <T, V> Function1<T, V>.inlineFunWithInvoke() {
+this
-this
this++
++this
this--
--this
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +ForbidExtensionCallsOnInlineFunctionalParameters
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -VAL_REASSIGNMENT -UNUSED_CHANGED_VALUE -VARIABLE_EXPECTED
@@ -40,7 +40,7 @@ open class A {
fun foo() {
<!UNRESOLVED_REFERENCE!>topLevelFun<!>()
<!UNRESOLVED_REFERENCE!>topLevelFun<!>(1)
<!UNRESOLVED_REFERENCE!>topLevelProperty<!><!UNRESOLVED_REFERENCE!>++<!>
<!UNRESOLVED_REFERENCE!>topLevelProperty<!><!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>++<!>
"".<!UNRESOLVED_REFERENCE!>topLevelExtensionFun<!>()
1.<!UNRESOLVED_REFERENCE!>topLevelExtensionFun<!>()
"".<!UNRESOLVED_REFERENCE!>topLevelExtensionProperty<!>
@@ -30,16 +30,22 @@ FILE: unsafeAssignmentExtra.fir.kt
lval value: R|Foo<kotlin/Int>| = R|/myBuilder|<R|kotlin/Int|>(<L> = myBuilder@fun R|Foo<kotlin/Int>|.<anonymous>(): R|kotlin/Unit| <inline=NoInline> {
this@R|special/anonymous|.R|SubstitutionOverride</Foo.b: R|kotlin/Array<Stub (chain inference): TypeVariable(T)>|>|.R|SubstitutionOverride<kotlin/Array.set: R|kotlin/Unit|>|(Int(0), Int(123))
this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>| = Int(45)
lval <unary>: R|kotlin/Int| = this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>|
this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>| = R|<local>/<unary>|.<Ambiguity: inc, [kotlin/inc, kotlin/inc]>#()
R|<local>/<unary>|
{
lval <unary>: R|kotlin/Int| = this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>|
this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>| = R|<local>/<unary>|.<Ambiguity: inc, [kotlin/inc, kotlin/inc]>#()
R|<local>/<unary>|
}
R|/bar|(::R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>|)
when () {
(this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>| is R|kotlin/Int|) -> {
this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>| = Int(67)
lval <unary>: R|kotlin/Int| = this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>|
this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>| = R|<local>/<unary>|.<Ambiguity: dec, [kotlin/dec, kotlin/dec]>#()
R|<local>/<unary>|
{
lval <unary>: R|kotlin/Int| = this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>|
this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>| = R|<local>/<unary>|.<Ambiguity: dec, [kotlin/dec, kotlin/dec]>#()
R|<local>/<unary>|
}
R|/bar|(::R|SubstitutionOverride</Foo.a: R|Stub (chain inference): TypeVariable(T)|>|)
}
}
@@ -185,22 +185,24 @@ FILE fqName:<root> fileName:/unaryOperators.kt
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> ($receiver:kotlin.Int) returnType:<root>.Result
$receiver: VALUE_PARAMETER name:$this$with type:kotlin.Int
BLOCK_BODY
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:<root>.Result [val]
GET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=<root>.Result origin=null
SET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=kotlin.Unit origin=EQ
CALL 'public final fun inc (_context_receiver_0: kotlin.Int): <root>.Result [operator] declared in <root>' type=<root>.Result origin=null
$receiver: GET_VAR 'val tmp_1: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
_context_receiver_0: GET_VAR '$this$with: kotlin.Int declared in <root>.box.<anonymous>' type=kotlin.Int origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
GET_VAR 'val tmp_1: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:<root>.Result [val]
GET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=<root>.Result origin=null
SET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=kotlin.Unit origin=EQ
CALL 'public final fun inc (_context_receiver_0: kotlin.Int): <root>.Result [operator] declared in <root>' type=<root>.Result origin=null
$receiver: GET_VAR 'val tmp_2: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
_context_receiver_0: GET_VAR '$this$with: kotlin.Int declared in <root>.box.<anonymous>' type=kotlin.Int origin=null
BLOCK type=<root>.Result origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:<root>.Result [val]
GET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=<root>.Result origin=null
SET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=kotlin.Unit origin=EQ
CALL 'public final fun inc (_context_receiver_0: kotlin.Int): <root>.Result [operator] declared in <root>' type=<root>.Result origin=null
$receiver: GET_VAR 'val tmp_1: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
_context_receiver_0: GET_VAR '$this$with: kotlin.Int declared in <root>.box.<anonymous>' type=kotlin.Int origin=null
GET_VAR 'val tmp_1: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
GET_VAR 'val tmp_2: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
BLOCK type=<root>.Result origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:<root>.Result [val]
GET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=<root>.Result origin=null
SET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=kotlin.Unit origin=EQ
CALL 'public final fun inc (_context_receiver_0: kotlin.Int): <root>.Result [operator] declared in <root>' type=<root>.Result origin=null
$receiver: GET_VAR 'val tmp_2: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
_context_receiver_0: GET_VAR '$this$with: kotlin.Int declared in <root>.box.<anonymous>' type=kotlin.Int origin=null
GET_VAR 'val tmp_2: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
CALL 'public final fun unaryMinus (_context_receiver_0: kotlin.Int): <root>.Result [operator] declared in <root>' type=<root>.Result origin=null
$receiver: GET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=<root>.Result origin=null
@@ -209,14 +211,15 @@ FILE fqName:<root> fileName:/unaryOperators.kt
CALL 'public final fun unaryPlus (_context_receiver_0: kotlin.Int): <root>.Result [operator] declared in <root>' type=<root>.Result origin=null
$receiver: GET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=<root>.Result origin=null
_context_receiver_0: GET_VAR '$this$with: kotlin.Int declared in <root>.box.<anonymous>' type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:<root>.Result [val]
GET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=<root>.Result origin=null
SET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=kotlin.Unit origin=EQ
CALL 'public final fun dec (_context_receiver_0: kotlin.Int): <root>.Result [operator] declared in <root>' type=<root>.Result origin=null
$receiver: GET_VAR 'val tmp_3: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
_context_receiver_0: GET_VAR '$this$with: kotlin.Int declared in <root>.box.<anonymous>' type=kotlin.Int origin=null
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): <root>.Result declared in <root>.box'
GET_VAR 'val tmp_3: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
BLOCK type=<root>.Result origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:<root>.Result [val]
GET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=<root>.Result origin=null
SET_VAR 'var result: <root>.Result [var] declared in <root>.box' type=kotlin.Unit origin=EQ
CALL 'public final fun dec (_context_receiver_0: kotlin.Int): <root>.Result [operator] declared in <root>' type=<root>.Result origin=null
$receiver: GET_VAR 'val tmp_3: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
_context_receiver_0: GET_VAR '$this$with: kotlin.Int declared in <root>.box.<anonymous>' type=kotlin.Int origin=null
GET_VAR 'val tmp_3: <root>.Result [val] declared in <root>.box.<anonymous>' type=<root>.Result origin=null
RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'
WHEN type=kotlin.String origin=IF
BRANCH
@@ -72,17 +72,23 @@ operator fun Result.dec(_context_receiver_0: Int): Result {
fun box(): String {
var result: Result = Result(i = 0)
with<Int, Result>(receiver = 1, block = local fun Int.<anonymous>(): Result {
val <unary>: Result = result
result = <unary>.inc(_context_receiver_0 = $this$with)
<unary> /*~> Unit */
val <unary>: Result = result
result = <unary>.inc(_context_receiver_0 = $this$with)
<unary> /*~> Unit */
{ // BLOCK
val <unary>: Result = result
result = <unary>.inc(_context_receiver_0 = $this$with)
<unary>
} /*~> Unit */
{ // BLOCK
val <unary>: Result = result
result = <unary>.inc(_context_receiver_0 = $this$with)
<unary>
} /*~> Unit */
result.unaryMinus(_context_receiver_0 = $this$with) /*~> Unit */
result.unaryPlus(_context_receiver_0 = $this$with) /*~> Unit */
val <unary>: Result = result
result = <unary>.dec(_context_receiver_0 = $this$with)
return <unary>
return { // BLOCK
val <unary>: Result = result
result = <unary>.dec(_context_receiver_0 = $this$with)
<unary>
}
}
) /*~> Unit */
return when {
@@ -104,16 +104,17 @@ FILE fqName:<root> fileName:/breakContinueInLoopHeader.kt
WHILE label=Outer origin=WHILE_LOOP
condition: CONST Boolean type=kotlin.Boolean value=true
body: BLOCK type=kotlin.Unit origin=null
SET_VAR 'var i: kotlin.Int [var] declared in <root>.test5' type=kotlin.Unit origin=PREFIX_INCR
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'var i: kotlin.Int [var] declared in <root>.test5' type=kotlin.Int origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
GET_VAR 'var i: kotlin.Int [var] declared in <root>.test5' type=kotlin.Int origin=null
BLOCK type=kotlin.Int origin=null
SET_VAR 'var i: kotlin.Int [var] declared in <root>.test5' type=kotlin.Unit origin=PREFIX_INCR
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'var i: kotlin.Int [var] declared in <root>.test5' type=kotlin.Int origin=null
GET_VAR 'var i: kotlin.Int [var] declared in <root>.test5' type=kotlin.Int origin=null
VAR name:j type:kotlin.Int [var]
CONST Int type=kotlin.Int value=0
BLOCK type=kotlin.Unit origin=null
DO_WHILE label=Inner origin=DO_WHILE_LOOP
body: COMPOSITE type=kotlin.Unit origin=DO_WHILE_LOOP
body: BLOCK type=kotlin.Int origin=null
SET_VAR 'var j: kotlin.Int [var] declared in <root>.test5' type=kotlin.Unit origin=PREFIX_INCR
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'var j: kotlin.Int [var] declared in <root>.test5' type=kotlin.Int origin=null
@@ -65,14 +65,16 @@ fun test4(ss: List<String>?) {
fun test5() {
var i: Int = 0
Outer@ while (true) { // BLOCK
i = i.inc()
i /*~> Unit */
{ // BLOCK
i = i.inc()
i
} /*~> Unit */
var j: Int = 0
{ // BLOCK
Inner@ do// COMPOSITE {
j = j.inc()
j
// } while (when {
Inner@ do{ // BLOCK
j = j.inc()
j
} while (when {
greaterOrEqual(arg0 = j, arg1 = 3) -> false
else -> break@Inner
})
@@ -111,11 +111,12 @@ FILE fqName:<root> fileName:/breakContinueInWhen.kt
BLOCK type=kotlin.Unit origin=null
DO_WHILE label=null origin=DO_WHILE_LOOP
body: COMPOSITE type=kotlin.Unit origin=DO_WHILE_LOOP
SET_VAR 'var k: kotlin.Int [var] declared in <root>.testContinueDoWhile' type=kotlin.Unit origin=PREFIX_INCR
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'var k: kotlin.Int [var] declared in <root>.testContinueDoWhile' type=kotlin.Int origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
GET_VAR 'var k: kotlin.Int [var] declared in <root>.testContinueDoWhile' type=kotlin.Int origin=null
BLOCK type=kotlin.Int origin=null
SET_VAR 'var k: kotlin.Int [var] declared in <root>.testContinueDoWhile' type=kotlin.Unit origin=PREFIX_INCR
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'var k: kotlin.Int [var] declared in <root>.testContinueDoWhile' type=kotlin.Int origin=null
GET_VAR 'var k: kotlin.Int [var] declared in <root>.testContinueDoWhile' type=kotlin.Int origin=null
WHEN type=kotlin.Unit origin=WHEN
BRANCH
if: CALL 'public final fun greater (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GT
@@ -60,8 +60,10 @@ fun testContinueDoWhile() {
var s: String = ""
{ // BLOCK
do// COMPOSITE {
k = k.inc()
k /*~> Unit */
{ // BLOCK
k = k.inc()
k
} /*~> Unit */
when {
greater(arg0 = k, arg1 = 2) -> continue
}
@@ -141,39 +141,36 @@ FILE fqName:<root> fileName:/complexAugmentedAssignment.kt
GET_VAR 'val tmp_3: kotlin.Int [val] declared in <root>.test1' type=kotlin.Int origin=null
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:<root>.X1 [val]
GET_OBJECT 'CLASS OBJECT name:X1 modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.X1
VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:kotlin.Int [val]
CALL 'public final fun <get-x1> (): kotlin.Int declared in <root>.X1' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'val tmp_4: <root>.X1 [val] declared in <root>.test2' type=<root>.X1 origin=null
CALL 'public final fun <set-x1> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.X1' type=kotlin.Unit origin=EQ
$this: GET_VAR 'val tmp_4: <root>.X1 [val] declared in <root>.test2' type=<root>.X1 origin=null
<set-?>: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:<root>.X1.X2 [val]
GET_OBJECT 'CLASS OBJECT name:X2 modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.X1.X2
VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Int [val]
CALL 'public final fun <get-x2> (): kotlin.Int declared in <root>.X1.X2' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'val tmp_6: <root>.X1.X2 [val] declared in <root>.test2' type=<root>.X1.X2 origin=null
CALL 'public final fun <set-x2> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.X1.X2' type=kotlin.Unit origin=EQ
$this: GET_VAR 'val tmp_6: <root>.X1.X2 [val] declared in <root>.test2' type=<root>.X1.X2 origin=null
<set-?>: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_7: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.Int [val]
CALL 'public final fun <get-x1> (): kotlin.Int declared in <root>.X1' type=kotlin.Int origin=GET_PROPERTY
$this: GET_OBJECT 'CLASS OBJECT name:X1 modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.X1
CALL 'public final fun <set-x1> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.X1' type=kotlin.Unit origin=EQ
$this: GET_OBJECT 'CLASS OBJECT name:X1 modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.X1
<set-?>: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_4: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
GET_VAR 'val tmp_4: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
GET_VAR 'val tmp_7: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:<root>.X1.X2.X3 [val]
GET_OBJECT 'CLASS OBJECT name:X3 modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.X1.X2.X3
VAR IR_TEMPORARY_VARIABLE name:tmp_9 type:kotlin.Int [val]
CALL 'public final fun <get-x3> (): kotlin.Int declared in <root>.X1.X2.X3' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'val tmp_8: <root>.X1.X2.X3 [val] declared in <root>.test2' type=<root>.X1.X2.X3 origin=null
CALL 'public final fun <set-x3> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.X1.X2.X3' type=kotlin.Unit origin=EQ
$this: GET_VAR 'val tmp_8: <root>.X1.X2.X3 [val] declared in <root>.test2' type=<root>.X1.X2.X3 origin=null
<set-?>: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_9: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:kotlin.Int [val]
CALL 'public final fun <get-x2> (): kotlin.Int declared in <root>.X1.X2' type=kotlin.Int origin=GET_PROPERTY
$this: GET_OBJECT 'CLASS OBJECT name:X2 modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.X1.X2
CALL 'public final fun <set-x2> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.X1.X2' type=kotlin.Unit origin=EQ
$this: GET_OBJECT 'CLASS OBJECT name:X2 modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.X1.X2
<set-?>: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
GET_VAR 'val tmp_9: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:kotlin.Int [val]
CALL 'public final fun <get-x3> (): kotlin.Int declared in <root>.X1.X2.X3' type=kotlin.Int origin=GET_PROPERTY
$this: GET_OBJECT 'CLASS OBJECT name:X3 modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.X1.X2.X3
CALL 'public final fun <set-x3> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.X1.X2.X3' type=kotlin.Unit origin=EQ
$this: GET_OBJECT 'CLASS OBJECT name:X3 modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.X1.X2.X3
<set-?>: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_6: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
GET_VAR 'val tmp_6: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
CLASS CLASS name:B modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.B
CONSTRUCTOR visibility:public <> (s:kotlin.Int) returnType:<root>.B [primary]
@@ -54,18 +54,21 @@ fun test1(a: IntArray) {
}
fun test2() {
val <receiver>: X1 = X1
val <unary>: Int = <receiver>.<get-x1>()
<receiver>.<set-x1>(<set-?> = <unary>.inc())
<unary> /*~> Unit */
val <receiver>: X2 = X2
val <unary>: Int = <receiver>.<get-x2>()
<receiver>.<set-x2>(<set-?> = <unary>.inc())
<unary> /*~> Unit */
val <receiver>: X3 = X3
val <unary>: Int = <receiver>.<get-x3>()
<receiver>.<set-x3>(<set-?> = <unary>.inc())
<unary> /*~> Unit */
{ // BLOCK
val <unary>: Int = X1.<get-x1>()
X1.<set-x1>(<set-?> = <unary>.inc())
<unary>
} /*~> Unit */
{ // BLOCK
val <unary>: Int = X2.<get-x2>()
X2.<set-x2>(<set-?> = <unary>.inc())
<unary>
} /*~> Unit */
{ // BLOCK
val <unary>: Int = X3.<get-x3>()
X3.<set-x3>(<set-?> = <unary>.inc())
<unary>
} /*~> Unit */
}
class B {
@@ -67,58 +67,48 @@ FILE fqName:<root> fileName:/incrementDecrement.kt
BLOCK_BODY
VAR name:p1 type:kotlin.Int [val]
BLOCK type=kotlin.Int origin=null
CALL 'public final fun <set-p> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=EQ
<set-?>: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Int [val]
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun <get-p> (): kotlin.Int declared in <root>' type=kotlin.Int origin=GET_PROPERTY
CALL 'public final fun <get-p> (): kotlin.Int declared in <root>' type=kotlin.Int origin=GET_PROPERTY
CALL 'public final fun <set-p> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=EQ
<set-?>: GET_VAR 'val tmp_2: kotlin.Int [val] declared in <root>.testPropPrefix' type=kotlin.Int origin=null
GET_VAR 'val tmp_2: kotlin.Int [val] declared in <root>.testPropPrefix' type=kotlin.Int origin=null
VAR name:p2 type:kotlin.Int [val]
BLOCK type=kotlin.Int origin=null
CALL 'public final fun <set-p> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=EQ
<set-?>: CALL 'public final fun dec (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.Int [val]
CALL 'public final fun dec (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun <get-p> (): kotlin.Int declared in <root>' type=kotlin.Int origin=GET_PROPERTY
CALL 'public final fun <get-p> (): kotlin.Int declared in <root>' type=kotlin.Int origin=GET_PROPERTY
CALL 'public final fun <set-p> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=EQ
<set-?>: GET_VAR 'val tmp_3: kotlin.Int [val] declared in <root>.testPropPrefix' type=kotlin.Int origin=null
GET_VAR 'val tmp_3: kotlin.Int [val] declared in <root>.testPropPrefix' type=kotlin.Int origin=null
FUN name:testPropPostfix visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR name:p1 type:kotlin.Int [val]
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Int [val]
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.Int [val]
CALL 'public final fun <get-p> (): kotlin.Int declared in <root>' type=kotlin.Int origin=GET_PROPERTY
CALL 'public final fun <set-p> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=EQ
<set-?>: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_2: kotlin.Int [val] declared in <root>.testPropPostfix' type=kotlin.Int origin=null
GET_VAR 'val tmp_2: kotlin.Int [val] declared in <root>.testPropPostfix' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_4: kotlin.Int [val] declared in <root>.testPropPostfix' type=kotlin.Int origin=null
GET_VAR 'val tmp_4: kotlin.Int [val] declared in <root>.testPropPostfix' type=kotlin.Int origin=null
VAR name:p2 type:kotlin.Int [val]
BLOCK type=kotlin.Int origin=null
CALL 'public final fun <set-p> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=EQ
<set-?>: CALL 'public final fun dec (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:kotlin.Int [val]
CALL 'public final fun dec (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun <get-p> (): kotlin.Int declared in <root>' type=kotlin.Int origin=GET_PROPERTY
CALL 'public final fun <get-p> (): kotlin.Int declared in <root>' type=kotlin.Int origin=GET_PROPERTY
CALL 'public final fun <set-p> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=EQ
<set-?>: GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.testPropPostfix' type=kotlin.Int origin=null
GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.testPropPostfix' type=kotlin.Int origin=null
FUN name:testArrayPrefix visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR name:a1 type:kotlin.Int [val]
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.IntArray [val]
CALL 'public final fun <get-arr> (): kotlin.IntArray declared in <root>' type=kotlin.IntArray origin=GET_PROPERTY
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.Int [val]
CONST Int type=kotlin.Int value=0
VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:kotlin.Int [val]
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun get (index: kotlin.Int): kotlin.Int [operator] declared in kotlin.IntArray' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_3: kotlin.IntArray [val] declared in <root>.testArrayPrefix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_4: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
CALL 'public final fun set (index: kotlin.Int, value: kotlin.Int): kotlin.Unit [operator] declared in kotlin.IntArray' type=kotlin.Unit origin=null
$this: GET_VAR 'val tmp_3: kotlin.IntArray [val] declared in <root>.testArrayPrefix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_4: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
value: GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
VAR name:a2 type:kotlin.Int [val]
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:kotlin.IntArray [val]
CALL 'public final fun <get-arr> (): kotlin.IntArray declared in <root>' type=kotlin.IntArray origin=GET_PROPERTY
VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Int [val]
CONST Int type=kotlin.Int value=0
VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:kotlin.Int [val]
CALL 'public final fun dec (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun get (index: kotlin.Int): kotlin.Int [operator] declared in kotlin.IntArray' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_6: kotlin.IntArray [val] declared in <root>.testArrayPrefix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_7: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
@@ -127,25 +117,25 @@ FILE fqName:<root> fileName:/incrementDecrement.kt
index: GET_VAR 'val tmp_7: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
value: GET_VAR 'val tmp_8: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
GET_VAR 'val tmp_8: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
FUN name:testArrayPostfix visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR name:a1 type:kotlin.Int [val]
VAR name:a2 type:kotlin.Int [val]
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_9 type:kotlin.IntArray [val]
CALL 'public final fun <get-arr> (): kotlin.IntArray declared in <root>' type=kotlin.IntArray origin=GET_PROPERTY
VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:kotlin.Int [val]
CONST Int type=kotlin.Int value=0
VAR IR_TEMPORARY_VARIABLE name:tmp_11 type:kotlin.Int [val]
CALL 'public final fun get (index: kotlin.Int): kotlin.Int [operator] declared in kotlin.IntArray' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_9: kotlin.IntArray [val] declared in <root>.testArrayPostfix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_10: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
CALL 'public final fun dec (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun get (index: kotlin.Int): kotlin.Int [operator] declared in kotlin.IntArray' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_9: kotlin.IntArray [val] declared in <root>.testArrayPrefix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_10: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
CALL 'public final fun set (index: kotlin.Int, value: kotlin.Int): kotlin.Unit [operator] declared in kotlin.IntArray' type=kotlin.Unit origin=null
$this: GET_VAR 'val tmp_9: kotlin.IntArray [val] declared in <root>.testArrayPostfix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_10: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
value: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_11: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
GET_VAR 'val tmp_11: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
VAR name:a2 type:kotlin.Int [val]
$this: GET_VAR 'val tmp_9: kotlin.IntArray [val] declared in <root>.testArrayPrefix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_10: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
value: GET_VAR 'val tmp_11: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
GET_VAR 'val tmp_11: kotlin.Int [val] declared in <root>.testArrayPrefix' type=kotlin.Int origin=null
FUN name:testArrayPostfix visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR name:a1 type:kotlin.Int [val]
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_12 type:kotlin.IntArray [val]
CALL 'public final fun <get-arr> (): kotlin.IntArray declared in <root>' type=kotlin.IntArray origin=GET_PROPERTY
@@ -158,6 +148,22 @@ FILE fqName:<root> fileName:/incrementDecrement.kt
CALL 'public final fun set (index: kotlin.Int, value: kotlin.Int): kotlin.Unit [operator] declared in kotlin.IntArray' type=kotlin.Unit origin=null
$this: GET_VAR 'val tmp_12: kotlin.IntArray [val] declared in <root>.testArrayPostfix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_13: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
value: CALL 'public final fun dec (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
value: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_14: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
GET_VAR 'val tmp_14: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
VAR name:a2 type:kotlin.Int [val]
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_15 type:kotlin.IntArray [val]
CALL 'public final fun <get-arr> (): kotlin.IntArray declared in <root>' type=kotlin.IntArray origin=GET_PROPERTY
VAR IR_TEMPORARY_VARIABLE name:tmp_16 type:kotlin.Int [val]
CONST Int type=kotlin.Int value=0
VAR IR_TEMPORARY_VARIABLE name:tmp_17 type:kotlin.Int [val]
CALL 'public final fun get (index: kotlin.Int): kotlin.Int [operator] declared in kotlin.IntArray' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_15: kotlin.IntArray [val] declared in <root>.testArrayPostfix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_16: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
CALL 'public final fun set (index: kotlin.Int, value: kotlin.Int): kotlin.Unit [operator] declared in kotlin.IntArray' type=kotlin.Unit origin=null
$this: GET_VAR 'val tmp_15: kotlin.IntArray [val] declared in <root>.testArrayPostfix' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_16: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
value: CALL 'public final fun dec (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_17: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
GET_VAR 'val tmp_17: kotlin.Int [val] declared in <root>.testArrayPostfix' type=kotlin.Int origin=null
@@ -35,12 +35,14 @@ fun testVarPostfix() {
fun testPropPrefix() {
val p1: Int = { // BLOCK
<set-p>(<set-?> = <get-p>().inc())
<get-p>()
val <unary-result>: Int = <get-p>().inc()
<set-p>(<set-?> = <unary-result>)
<unary-result>
}
val p2: Int = { // BLOCK
<set-p>(<set-?> = <get-p>().dec())
<get-p>()
val <unary-result>: Int = <get-p>().dec()
<set-p>(<set-?> = <unary-result>)
<unary-result>
}
}
@@ -51,8 +53,9 @@ fun testPropPostfix() {
<unary>
}
val p2: Int = { // BLOCK
<set-p>(<set-?> = <get-p>().dec())
<get-p>()
val <unary-result>: Int = <get-p>().dec()
<set-p>(<set-?> = <unary-result>)
<unary-result>
}
}
@@ -9,17 +9,18 @@ FILE fqName:<root> fileName:/javaSyntheticGenericPropertyAccess.kt
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
x: CONST Int type=kotlin.Int value=1
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.J<F of <root>.test> [val]
GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val]
CALL 'public open fun getFoo (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'val tmp_0: <root>.J<F of <root>.test> [val] declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'val tmp_0: <root>.J<F of <root>.test> [val] declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
x: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.J<F of <root>.test> [val]
GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val]
CALL 'public open fun getFoo (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'val tmp_0: <root>.J<F of <root>.test> [val] declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'val tmp_0: <root>.J<F of <root>.test> [val] declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
x: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
x: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
@@ -1,9 +1,11 @@
fun <F : Any?> test(j: J<F>) {
j.getFoo() /*~> Unit */
j.setFoo(x = 1)
val <receiver>: J<F> = j
val <unary>: Int = <receiver>.getFoo()
<receiver>.setFoo(x = <unary>.inc())
<unary> /*~> Unit */
{ // BLOCK
val <receiver>: J<F> = j
val <unary>: Int = <receiver>.getFoo()
<receiver>.setFoo(x = <unary>.inc())
<unary>
} /*~> Unit */
j.setFoo(x = j.getFoo().plus(other = 1))
}
@@ -8,17 +8,18 @@ FILE fqName:<root> fileName:/javaSyntheticPropertyAccess.kt
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'j: <root>.J declared in <root>.test' type=<root>.J origin=null
x: CONST Int type=kotlin.Int value=1
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.J [val]
GET_VAR 'j: <root>.J declared in <root>.test' type=<root>.J origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val]
CALL 'public open fun getFoo (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'val tmp_0: <root>.J [val] declared in <root>.test' type=<root>.J origin=null
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'val tmp_0: <root>.J [val] declared in <root>.test' type=<root>.J origin=null
x: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.J [val]
GET_VAR 'j: <root>.J declared in <root>.test' type=<root>.J origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val]
CALL 'public open fun getFoo (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'val tmp_0: <root>.J [val] declared in <root>.test' type=<root>.J origin=null
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'val tmp_0: <root>.J [val] declared in <root>.test' type=<root>.J origin=null
x: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'j: <root>.J declared in <root>.test' type=<root>.J origin=null
x: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
@@ -1,9 +1,11 @@
fun test(j: J) {
j.getFoo() /*~> Unit */
j.setFoo(x = 1)
val <receiver>: J = j
val <unary>: Int = <receiver>.getFoo()
<receiver>.setFoo(x = <unary>.inc())
<unary> /*~> Unit */
{ // BLOCK
val <receiver>: J = j
val <unary>: Int = <receiver>.getFoo()
<receiver>.setFoo(x = <unary>.inc())
<unary>
} /*~> Unit */
j.setFoo(x = j.getFoo().plus(other = 1))
}
@@ -74,44 +74,42 @@ FILE fqName:test fileName:/safeCallWithIncrementDecrement.kt
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:test.C [val]
GET_VAR 'val tmp_1: test.C? [val] declared in test.testProperty' type=test.C? origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.Int [val]
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Int [val]
CALL 'public final fun <get-p> (): kotlin.Int declared in test' type=kotlin.Int origin=GET_PROPERTY
$receiver: GET_VAR 'val tmp_2: test.C [val] declared in test.testProperty' type=test.C origin=null
$receiver: GET_VAR 'val tmp_1: test.C? [val] declared in test.testProperty' type=test.C? origin=null
CALL 'public final fun <set-p> (value: kotlin.Int): kotlin.Unit declared in test' type=kotlin.Unit origin=EQ
$receiver: GET_VAR 'val tmp_2: test.C [val] declared in test.testProperty' type=test.C origin=null
$receiver: GET_VAR 'val tmp_1: test.C? [val] declared in test.testProperty' type=test.C? origin=null
value: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_3: kotlin.Int [val] declared in test.testProperty' type=kotlin.Int origin=null
GET_VAR 'val tmp_3: kotlin.Int [val] declared in test.testProperty' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_2: kotlin.Int [val] declared in test.testProperty' type=kotlin.Int origin=null
GET_VAR 'val tmp_2: kotlin.Int [val] declared in test.testProperty' type=kotlin.Int origin=null
FUN name:testArrayAccess visibility:public modality:FINAL <> (nc:test.C?) returnType:kotlin.Unit
VALUE_PARAMETER name:nc index:0 type:test.C?
BLOCK_BODY
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
BLOCK type=kotlin.Int? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:test.C? [val]
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:test.C? [val]
GET_VAR 'nc: test.C? declared in test.testArrayAccess' type=test.C? origin=null
WHEN type=kotlin.Int? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_4: test.C? [val] declared in test.testArrayAccess' type=test.C? origin=null
arg0: GET_VAR 'val tmp_3: test.C? [val] declared in test.testArrayAccess' type=test.C? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: BLOCK type=kotlin.Int origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:kotlin.Int [val]
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.Int [val]
CALL 'public final fun <get-p> (): kotlin.Int declared in test' type=kotlin.Int origin=GET_PROPERTY
$receiver: GET_VAR 'val tmp_4: test.C? [val] declared in test.testArrayAccess' type=test.C? origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:kotlin.Int [val]
$receiver: GET_VAR 'val tmp_3: test.C? [val] declared in test.testArrayAccess' type=test.C? origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:kotlin.Int [val]
CONST Int type=kotlin.Int value=0
VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Int [val]
VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:kotlin.Int [val]
CALL 'public final fun get (index: kotlin.Int): kotlin.Int [operator] declared in test' type=kotlin.Int origin=null
$receiver: GET_VAR 'val tmp_5: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
index: GET_VAR 'val tmp_6: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
$receiver: GET_VAR 'val tmp_4: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
index: GET_VAR 'val tmp_5: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
CALL 'public final fun set (index: kotlin.Int, value: kotlin.Int): kotlin.Unit [operator] declared in test' type=kotlin.Unit origin=null
$receiver: GET_VAR 'val tmp_5: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
index: GET_VAR 'val tmp_6: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
$receiver: GET_VAR 'val tmp_4: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
index: GET_VAR 'val tmp_5: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
value: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_7: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
GET_VAR 'val tmp_7: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_6: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
GET_VAR 'val tmp_6: kotlin.Int [val] declared in test.testArrayAccess' type=kotlin.Int origin=null
@@ -39,9 +39,8 @@ fun testProperty(nc: C?) {
when {
EQEQ(arg0 = tmp1_safe_receiver, arg1 = null) -> null
else -> { // BLOCK
val <receiver>: C = tmp1_safe_receiver
val <unary>: Int = <receiver>.<get-p>()
<receiver>.<set-p>(value = <unary>.inc())
val <unary>: Int = tmp1_safe_receiver.<get-p>()
tmp1_safe_receiver.<set-p>(value = <unary>.inc())
<unary>
}
}
@@ -50,7 +50,7 @@ FILE fqName:<root> fileName:/whileDoWhile.kt
arg1: CONST Int type=kotlin.Int value=15
BLOCK type=kotlin.Unit origin=null
DO_WHILE label=null origin=DO_WHILE_LOOP
body: COMPOSITE type=kotlin.Unit origin=DO_WHILE_LOOP
body: BLOCK type=kotlin.Int origin=POSTFIX_INCR
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.Int [val]
GET_VAR 'var x: kotlin.Int [var] declared in <root>.test' type=kotlin.Int origin=null
SET_VAR 'var x: kotlin.Int [var] declared in <root>.test' type=kotlin.Unit origin=POSTFIX_INCR
@@ -24,11 +24,11 @@ fun test() {
} while (less(arg0 = x, arg1 = 15))
}
{ // BLOCK
do// COMPOSITE {
val <unary>: Int = x
x = <unary>.inc()
<unary>
// } while (less(arg0 = x, arg1 = 20))
do{ // BLOCK
val <unary>: Int = x
x = <unary>.inc()
<unary>
} while (less(arg0 = x, arg1 = 20))
}
}
@@ -543,7 +543,7 @@ FILE fqName:<root> fileName:/ArrayMap.kt
BLOCK_BODY
BLOCK type=kotlin.Unit origin=null
DO_WHILE label=null origin=DO_WHILE_LOOP
body: COMPOSITE type=kotlin.Unit origin=DO_WHILE_LOOP
body: BLOCK type=kotlin.Int origin=POSTFIX_INCR
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val]
CALL 'private final fun <get-index> (): kotlin.Int declared in <root>.ArrayMapImpl.iterator.<no name provided>' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR '<this>: <root>.ArrayMapImpl.iterator.<no name provided><T of <root>.ArrayMapImpl> declared in <root>.ArrayMapImpl.iterator.<no name provided>.computeNext' type=<root>.ArrayMapImpl.iterator.<no name provided><T of <root>.ArrayMapImpl> origin=null
@@ -224,11 +224,11 @@ internal class ArrayMapImpl<T : Any> : ArrayMap<T> {
protected override fun computeNext() {
{ // BLOCK
do// COMPOSITE {
val <unary>: Int = <this>.<get-index>()
<this>.<set-index>(<set-?> = <unary>.inc())
<unary>
// } while (when {
do{ // BLOCK
val <unary>: Int = <this>.<get-index>()
<this>.<set-index>(<set-?> = <unary>.inc())
<unary>
} while (when {
less(arg0 = <this>.<get-index>(), arg1 = <this>.<get-data>().<get-size>()) -> EQEQ(arg0 = <this>.<get-data>().get(index = <this>.<get-index>()), arg1 = null)
else -> false
})
@@ -357,6 +357,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/IncorrectCharacterLiterals.kt");
}
@Test
@TestMetadata("incrementDecrementOnFullyQualified.kt")
public void testIncrementDecrementOnFullyQualified() throws Exception {
runTest("compiler/testData/diagnostics/tests/incrementDecrementOnFullyQualified.kt");
}
@Test
@TestMetadata("incrementDecrementOnObject.kt")
public void testIncrementDecrementOnObject() throws Exception {
runTest("compiler/testData/diagnostics/tests/incrementDecrementOnObject.kt");
}
@Test
@TestMetadata("InferNullabilityInThenBlock.kt")
public void testInferNullabilityInThenBlock() throws Exception {
@@ -25913,6 +25913,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -46811,12 +46817,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -26873,6 +26873,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -49043,12 +49049,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -21801,6 +21801,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/rangeFromCollection.kt");
@@ -37903,11 +37908,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/inheritedPropertyInClassObject.kt");
@@ -5,7 +5,7 @@
fun case1() {
var a = Case1()
val res: Any? = <!RESULT_TYPE_MISMATCH!>++a<!>
val res: Any? = <!RESULT_TYPE_MISMATCH!>++<!>a
}
@@ -22,7 +22,7 @@ class B() {}
fun case2() {
var a = Case2()
val res: Any? = <!RESULT_TYPE_MISMATCH!>++a<!>
val res: Any? = <!RESULT_TYPE_MISMATCH!>++<!>a
}
class Case2() : C() {
@@ -1,37 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION
// SKIP_TXT
// TESTCASE NUMBER: 1
fun case1() {
var a = Case1()
val res: Any? = <!RESULT_TYPE_MISMATCH!>--a<!>
}
class Case1() {
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun dec(): B {
TODO()
}
}
class B() {}
// TESTCASE NUMBER: 2
fun case2() {
var a = Case2()
val res: Any? = <!RESULT_TYPE_MISMATCH!>--a<!>
}
class Case2() : C() {
var i = 0
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun dec(): C {
TODO()
}
}
open class C() {}
@@ -1,5 +1,6 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION
// SKIP_TXT
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
@@ -20821,6 +20821,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -34723,12 +34729,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -20839,6 +20839,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -34909,12 +34915,24 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -20839,6 +20839,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -34909,12 +34915,24 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -20839,6 +20839,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -34909,12 +34915,24 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -23762,6 +23762,12 @@ public class K2NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -38492,12 +38498,24 @@ public class K2NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -23540,6 +23540,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@Test
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@Test
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
@@ -38012,12 +38018,24 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@Test
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@Test
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@Test
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@Test
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
@@ -18449,6 +18449,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
}
@TestMetadata("prefixIncDecFir.kt")
public void testPrefixIncDecFir() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
}
@TestMetadata("rangeFromCollection.kt")
public void testRangeFromCollection() throws Exception {
runTest("compiler/testData/codegen/box/intrinsics/rangeFromCollection.kt");
@@ -31263,11 +31268,21 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
}
@TestMetadata("incInClassObjectFir.kt")
public void testIncInClassObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
}
@TestMetadata("incInObject.kt")
public void testIncInObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
}
@TestMetadata("incInObjectFir.kt")
public void testIncInObjectFir() throws Exception {
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
}
@TestMetadata("inheritedPropertyInClassObject.kt")
public void testInheritedPropertyInClassObject() throws Exception {
runTest("compiler/testData/codegen/box/statics/inheritedPropertyInClassObject.kt");