[FIR] Add desugaring of array assignments and resolve of it

#KT-37516 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-03-16 17:00:08 +03:00
parent 26f919df03
commit 2b986194fb
41 changed files with 608 additions and 233 deletions
@@ -856,6 +856,7 @@ class Fir2IrVisitor(
private fun FirStatement.toIrStatement(): IrStatement? {
if (this is FirTypeAlias) return null
if (this is FirUnitExpression) return toIrExpression()
if (this is FirBlock) return toIrExpression()
return accept(this@Fir2IrVisitor, null) as IrStatement
}
@@ -192,6 +192,7 @@ class ExpressionsConverter(
lateinit var operationTokenName: String
var leftArgNode: LighterASTNode? = null
var rightArgAsFir: FirExpression = buildErrorExpression(null, FirSimpleDiagnostic("No right operand", DiagnosticKind.Syntax))
var rightArg: LighterASTNode? = null
binaryExpression.forEachChildren {
when (it.tokenType) {
OPERATION_REFERENCE -> {
@@ -203,6 +204,7 @@ class ExpressionsConverter(
leftArgNode = it
} else {
rightArgAsFir = getAsFirExpression(it, "No right operand")
rightArg = it
}
}
}
@@ -241,7 +243,7 @@ class ExpressionsConverter(
} else {
val firOperation = operationToken.toFirOperation()
if (firOperation in FirOperation.ASSIGNMENTS) {
return leftArgNode.generateAssignment(null, rightArgAsFir, firOperation) { getAsFirExpression(this) }
return leftArgNode.generateAssignment(null, rightArg, rightArgAsFir, firOperation) { getAsFirExpression(this) }
} else {
buildOperatorCall {
source = binaryExpression.toFirSourceElement()
@@ -11,10 +11,7 @@ import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.addDeclaration
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
@@ -42,6 +39,7 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.KtUnaryExpression
import org.jetbrains.kotlin.resolve.constants.evaluate.*
import org.jetbrains.kotlin.util.OperatorNameConventions
//T can be either PsiElement, or LighterASTNode
abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Context<T> = Context()) {
@@ -387,6 +385,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
val resultVar = generateTemporaryVariable(this@BaseFirBuilder.baseSession, source, resultName, resultInitializer)
val assignment = argument.generateAssignment(
source,
argument,
if (prefix && argument.elementType != REFERENCE_EXPRESSION)
generateResolvedAccessExpression(source, resultVar)
else
@@ -463,48 +462,24 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
fun T?.generateAssignment(
baseSource: FirSourceElement?,
value: FirExpression,
rhs: T?,
value: FirExpression, // value is FIR for rhs
operation: FirOperation,
convert: T.() -> FirExpression
): FirStatement {
val tokenType = this?.elementType
if (tokenType == PARENTHESIZED) {
return this!!.getExpressionInParentheses().generateAssignment(baseSource, value, operation, convert)
return this!!.getExpressionInParentheses().generateAssignment(baseSource, rhs, value, operation, convert)
}
if (tokenType == ARRAY_ACCESS_EXPRESSION) {
require(this != null)
if (operation == FirOperation.ASSIGN) {
context.arraySetArgument[this!!] = value
context.arraySetArgument[this] = value
}
val firArrayAccess = this!!.convert() as FirFunctionCall
if (operation == FirOperation.ASSIGN) {
return firArrayAccess
}
val arraySetCallBuilder = FirArraySetCallBuilder().apply {
source = baseSource
rValue = value
this.operation = operation
indexes += firArrayAccess.arguments
argumentList = buildArraySetArgumentList(rValue, indexes)
}
val arrayExpression = this.getChildNodeByType(REFERENCE_EXPRESSION)
if (arrayExpression != null) {
return arraySetCallBuilder.apply {
calleeReference = initializeLValue(arrayExpression) { convert() as? FirQualifiedAccess }
}.build()
}
val psiArrayExpression = firArrayAccess.explicitReceiver?.psi
return buildBlock {
source = psiArrayExpression?.toFirSourceElement()
val name = Name.special("<array-set>")
statements += generateTemporaryVariable(
this@BaseFirBuilder.baseSession, this@generateAssignment.getSourceOrNull(), name, firArrayAccess.explicitReceiver!!
)
statements += arraySetCallBuilder.apply {
calleeReference = buildSimpleNamedReference {
source = psiArrayExpression?.toFirSourceElement()
this.name = name
}
}.build()
return if (operation == FirOperation.ASSIGN) {
this.convert()
} else {
generateArraySetCall(baseSource, operation, rhs, convert)
}
}
@@ -531,6 +506,120 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
}
private fun T.generateArraySetCall(
baseSource: FirSourceElement?,
operation: FirOperation,
rhs: T?,
convert: T.() -> FirExpression
): FirStatement {
return buildArraySetCall {
source = baseSource
this.operation = operation
assignCall = generateAugmentedCallForAugmentedArraySetCall(operation, rhs, convert)
setGetBlock = generateSetGetBlockForAugmentedArraySetCall(baseSource, operation, rhs, convert)
}
}
private fun T.generateAugmentedCallForAugmentedArraySetCall(
operation: FirOperation,
rhs: T?,
convert: T.() -> FirExpression
): FirFunctionCall {
/*
* Desugarings of a[x, y] += z to
* a.get(x, y).plusAssign(z)
*/
return buildFunctionCall {
calleeReference = buildSimpleNamedReference {
name = FirOperationNameConventions.ASSIGNMENTS.getValue(operation)
}
explicitReceiver = convert()
argumentList = buildArgumentList {
arguments += rhs?.convert() ?: buildErrorExpression(
null,
FirSimpleDiagnostic("No value for array set", DiagnosticKind.Syntax)
)
}
}
}
private fun T.generateSetGetBlockForAugmentedArraySetCall(
baseSource: FirSourceElement?,
operation: FirOperation,
rhs: T?,
convert: T.() -> FirExpression
): FirBlock {
/*
* Desugarings of a[x, y] += z to
* {
* val tmp_a = a
* val tmp_x = x
* val tmp_y = y
* tmp_a.set(tmp_x, tmp_a.get(tmp_x, tmp_y).plus(z))
* }
*/
return buildBlock {
val baseCall = convert() as FirFunctionCall
val arrayVariable = generateTemporaryVariable(
baseSession,
source = null,
"<array>",
baseCall.explicitReceiver ?: buildErrorExpression {
source = baseSource
diagnostic = FirSimpleDiagnostic("No receiver for array access", DiagnosticKind.Syntax)
}
)
statements += arrayVariable
val indexVariables = baseCall.arguments.mapIndexed { i, index ->
generateTemporaryVariable(baseSession, source = null, "<index_$i>", index)
}
statements += indexVariables
statements += buildFunctionCall {
source = baseSource
explicitReceiver = arrayVariable.toQualifiedAccess()
calleeReference = buildSimpleNamedReference {
name = OperatorNameConventions.SET
}
argumentList = buildArgumentList {
for (indexVariable in indexVariables) {
arguments += indexVariable.toQualifiedAccess()
}
val getCall = buildFunctionCall {
explicitReceiver = arrayVariable.toQualifiedAccess()
calleeReference = buildSimpleNamedReference {
name = OperatorNameConventions.GET
}
argumentList = buildArgumentList {
for (indexVariable in indexVariables) {
arguments += indexVariable.toQualifiedAccess()
}
}
}
val operatorCall = buildFunctionCall {
calleeReference = buildSimpleNamedReference {
name = FirOperationNameConventions.ASSIGNMENTS_TO_SIMPLE_OPERATOR.getValue(operation)
}
explicitReceiver = getCall
argumentList = buildArgumentList {
arguments += rhs?.convert() ?: buildErrorExpression(
null,
FirSimpleDiagnostic(
"No value for array set",
DiagnosticKind.Syntax
)
)
}
}
arguments += operatorCall
}
}
}
}
fun List<Pair<T, FirProperty>>.generateComponentFunctions(
session: FirSession, firClassBuilder: AbstractFirRegularClassBuilder, packageFqName: FqName, classFqName: FqName,
firPrimaryConstructor: FirConstructor,
@@ -631,4 +720,10 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
)
}
private fun FirVariable<*>.toQualifiedAccess(): FirQualifiedAccessExpression = buildQualifiedAccessExpression {
calleeReference = buildResolvedNamedReference {
name = this@toQualifiedAccess.name
resolvedSymbol = this@toQualifiedAccess.symbol
}
}
}
@@ -1396,7 +1396,7 @@ class RawFirBuilder(
} else {
val firOperation = operationToken.toFirOperation()
if (firOperation in FirOperation.ASSIGNMENTS) {
return expression.left.generateAssignment(source, rightArgument, firOperation) {
return expression.left.generateAssignment(source, expression.right, rightArgument, firOperation) {
(this as KtExpression).toFirExpression("Incorrect expression in assignment: ${expression.text}")
}
} else {
@@ -70,7 +70,6 @@ class VariableStorage(val session: FirSession) {
is FirQualifiedAccessExpression -> originalFir
is FirWhenSubjectExpression -> originalFir.whenSubject.whenExpression.subject as? FirQualifiedAccessExpression
is FirVariableAssignment -> originalFir
is FirArraySetCall -> originalFir
else -> null
}
@@ -169,6 +169,10 @@ open class FirBodyResolveTransformer(
return expressionsTransformer.transformDelegatedConstructorCall(delegatedConstructorCall, data)
}
override fun transformArraySetCall(arraySetCall: FirArraySetCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
return expressionsTransformer.transformArraySetCall(arraySetCall, data)
}
// ------------------------------------- Declarations -------------------------------------
override fun transformDeclaration(declaration: FirDeclaration, data: ResolutionMode): CompositeTransformResult<FirDeclaration> {
@@ -23,9 +23,7 @@ import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.candidate
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirOperatorAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirTypeMismatchError
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirVariableExpectedError
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
@@ -630,6 +628,63 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
}
}
@OptIn(ExperimentalStdlibApi::class)
override fun transformArraySetCall(arraySetCall: FirArraySetCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
assert(arraySetCall.operation in FirOperation.ASSIGNMENTS)
assert(arraySetCall.operation != FirOperation.ASSIGN)
val operatorName = FirOperationNameConventions.ASSIGNMENTS.getValue(arraySetCall.operation)
val firstCalls = with(arraySetCall.setGetBlock.statements.last() as FirFunctionCall) setCall@{
buildList {
add(this@setCall)
with(arguments.last() as FirFunctionCall) plusCall@{
add(this@plusCall)
add(explicitReceiver as FirFunctionCall)
}
}
}
val secondCalls = listOf(
arraySetCall.assignCall,
arraySetCall.assignCall.explicitReceiver as FirFunctionCall
)
val firstResult = withLocalScopeCleanup {
arraySetCall.setGetBlock.transformSingle(transformer, ResolutionMode.ContextIndependent)
}
val secondResult = arraySetCall.assignCall.transformSingle(transformer, ResolutionMode.ContextIndependent)
val firstSucceed = firstCalls.all { it.typeRef !is FirErrorTypeRef }
val secondSucceed = secondCalls.all { it.typeRef !is FirErrorTypeRef }
val result: FirStatement = when {
firstSucceed && secondSucceed -> {
arraySetCall.also {
it.replaceCalleeReference(
buildErrorNamedReference {
// TODO: add better diagnostic
source = arraySetCall.source
diagnostic = FirAmbiguityError(operatorName, emptyList())
}
)
}
}
firstSucceed -> firstResult
secondSucceed -> secondResult
else -> {
arraySetCall.also {
it.replaceCalleeReference(
buildErrorNamedReference {
source = arraySetCall.source
diagnostic = FirUnresolvedNameError(operatorName)
}
)
}
}
}
return result.compose()
}
// ------------------------------------------------------------------------------------------------
internal fun <T> storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression {
@@ -0,0 +1,31 @@
// ISSUE: KT-37516
class A<T> {
operator fun get(index: Int): T = null!!
operator fun set(index: Int, value: T) {}
}
class B {
operator fun plusAssign(other: B) {}
}
class C {
operator fun plus(other: C): C = this
}
class D {
operator fun plusAssign(other: D) {}
operator fun plus(other: D): D = this
}
fun test_1(a: A<B>) {
a[0] = B() // set
}
fun test_2(a: A<C>) {
a[0] = C() // set
}
fun test_3(a: A<D>) {
a[0] = D() // set
}
@@ -0,0 +1,55 @@
FILE: arraySet.kt
public final class A<T> : R|kotlin/Any| {
public constructor<T>(): R|A<T>| {
super<R|kotlin/Any|>()
}
public final operator fun get(index: R|kotlin/Int|): R|T| {
^get Null(null)!!
}
public final operator fun set(index: R|kotlin/Int|, value: R|T|): R|kotlin/Unit| {
}
}
public final class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
public final operator fun plusAssign(other: R|B|): R|kotlin/Unit| {
}
}
public final class C : R|kotlin/Any| {
public constructor(): R|C| {
super<R|kotlin/Any|>()
}
public final operator fun plus(other: R|C|): R|C| {
^plus this@R|/C|
}
}
public final class D : R|kotlin/Any| {
public constructor(): R|D| {
super<R|kotlin/Any|>()
}
public final operator fun plusAssign(other: R|D|): R|kotlin/Unit| {
}
public final operator fun plus(other: R|D|): R|D| {
^plus this@R|/D|
}
}
public final fun test_1(a: R|A<B>|): R|kotlin/Unit| {
R|<local>/a|.R|FakeOverride</A.set: R|kotlin/Unit|>|(Int(0), R|/B.B|())
}
public final fun test_2(a: R|A<C>|): R|kotlin/Unit| {
R|<local>/a|.R|FakeOverride</A.set: R|kotlin/Unit|>|(Int(0), R|/C.C|())
}
public final fun test_3(a: R|A<D>|): R|kotlin/Unit| {
R|<local>/a|.R|FakeOverride</A.set: R|kotlin/Unit|>|(Int(0), R|/D.D|())
}
@@ -0,0 +1,36 @@
// ISSUE: KT-37516
class A<T> {
operator fun get(index: Int): T = null!!
operator fun set(index: Int, value: T) {}
}
class B {
operator fun plusAssign(other: B) {}
}
class C {
operator fun plus(other: C): C = this
}
class D {
operator fun plusAssign(other: D) {}
operator fun plus(other: D): D = this
}
fun test_1(a: A<B>) {
// foo().bar()[0] += x
a[0] += B() // get, plusAssign
}
fun test_2(a: A<C>) {
a[0] += C() // get, set, plus
}
fun test_3(a: A<D>) {
<!AMBIGUITY!>a[0] += D()<!> // ambiguity
}
fun test_4(b: B) {
<!UNRESOLVED_REFERENCE!><!UNRESOLVED_REFERENCE!>b[0]<!> += B()<!> // unresolved
}
@@ -0,0 +1,63 @@
FILE: arraySetWithOperation.kt
public final class A<T> : R|kotlin/Any| {
public constructor<T>(): R|A<T>| {
super<R|kotlin/Any|>()
}
public final operator fun get(index: R|kotlin/Int|): R|T| {
^get Null(null)!!
}
public final operator fun set(index: R|kotlin/Int|, value: R|T|): R|kotlin/Unit| {
}
}
public final class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
public final operator fun plusAssign(other: R|B|): R|kotlin/Unit| {
}
}
public final class C : R|kotlin/Any| {
public constructor(): R|C| {
super<R|kotlin/Any|>()
}
public final operator fun plus(other: R|C|): R|C| {
^plus this@R|/C|
}
}
public final class D : R|kotlin/Any| {
public constructor(): R|D| {
super<R|kotlin/Any|>()
}
public final operator fun plusAssign(other: R|D|): R|kotlin/Unit| {
}
public final operator fun plus(other: R|D|): R|D| {
^plus this@R|/D|
}
}
public final fun test_1(a: R|A<B>|): R|kotlin/Unit| {
R|<local>/a|.R|FakeOverride</A.get: R|B|>|(Int(0)).R|/B.plusAssign|(R|/B.B|())
}
public final fun test_2(a: R|A<C>|): R|kotlin/Unit| {
{
lval <<array>>: R|A<C>| = R|<local>/a|
lval <<index_0>>: R|kotlin/Int| = Int(0)
R|<local>/<<array>>|.R|FakeOverride</A.set: R|kotlin/Unit|>|(R|<local>/<<index_0>>|, R|<local>/<<array>>|.R|FakeOverride</A.get: R|C|>|(R|<local>/<<index_0>>|).R|/C.plus|(R|/C.C|()))
}
}
public final fun test_3(a: R|A<D>|): R|kotlin/Unit| {
ArraySet:[R|<local>/a|.R|FakeOverride</A.get: R|D|>|(Int(0)).R|/D.plusAssign|(R|/D.D|())]
}
public final fun test_4(b: R|B|): R|kotlin/Unit| {
ArraySet:[R|<local>/b|.<Unresolved name: get>#(Int(0)).<Unresolved name: plusAssign>#(R|/B.B|())]
}
@@ -526,6 +526,29 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/arrays")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Arrays extends AbstractFirDiagnosticsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInArrays() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/arrays"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("arraySet.kt")
public void testArraySet() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arrays/arraySet.kt");
}
@TestMetadata("arraySetWithOperation.kt")
public void testArraySetWithOperation() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arrays/arraySetWithOperation.kt");
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/builtins")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -526,6 +526,29 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/arrays")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Arrays extends AbstractFirDiagnosticsWithLightTreeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInArrays() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/arrays"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("arraySet.kt")
public void testArraySet() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arrays/arraySet.kt");
}
@TestMetadata("arraySetWithOperation.kt")
public void testArraySetWithOperation() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arrays/arraySetWithOperation.kt");
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/builtins")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.fir.FirPureAbstractElement
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.visitors.*
/*
@@ -16,34 +15,15 @@ import org.jetbrains.kotlin.fir.visitors.*
* DO NOT MODIFY IT MANUALLY
*/
abstract class FirArraySetCall : FirPureAbstractElement(), FirQualifiedAccess, FirCall {
abstract class FirArraySetCall : FirPureAbstractElement(), FirStatement {
abstract override val source: FirSourceElement?
abstract override val annotations: List<FirAnnotationCall>
abstract override val safe: Boolean
abstract override val typeArguments: List<FirTypeProjection>
abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression
abstract override val calleeReference: FirReference
abstract override val argumentList: FirArgumentList
abstract val rValue: FirExpression
abstract val assignCall: FirFunctionCall
abstract val setGetBlock: FirBlock
abstract val operation: FirOperation
abstract val lValue: FirReference
abstract val indexes: List<FirExpression>
abstract val calleeReference: FirReference
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitArraySetCall(this, data)
abstract override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirArraySetCall
abstract override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirArraySetCall
abstract override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirArraySetCall
abstract override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirArraySetCall
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirArraySetCall
abstract fun <D> transformRValue(transformer: FirTransformer<D>, data: D): FirArraySetCall
abstract fun <D> transformIndexes(transformer: FirTransformer<D>, data: D): FirArraySetCall
abstract fun replaceCalleeReference(newCalleeReference: FirReference)
}
@@ -10,16 +10,13 @@ import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirArgumentList
import org.jetbrains.kotlin.fir.expressions.FirArraySetCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirOperation
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirArraySetCallImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirModifiableQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.references.impl.FirStubReference
import org.jetbrains.kotlin.fir.visitors.*
/*
@@ -28,34 +25,22 @@ import org.jetbrains.kotlin.fir.visitors.*
*/
@FirBuilderDsl
class FirArraySetCallBuilder : FirQualifiedAccessBuilder, FirAnnotationContainerBuilder {
class FirArraySetCallBuilder : FirAnnotationContainerBuilder {
override var source: FirSourceElement? = null
override val annotations: MutableList<FirAnnotationCall> = mutableListOf()
override var safe: Boolean = false
override val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
override var explicitReceiver: FirExpression? = null
override var dispatchReceiver: FirExpression = FirNoReceiverExpression
override var extensionReceiver: FirExpression = FirNoReceiverExpression
lateinit var calleeReference: FirReference
lateinit var argumentList: FirArgumentList
lateinit var rValue: FirExpression
lateinit var assignCall: FirFunctionCall
lateinit var setGetBlock: FirBlock
lateinit var operation: FirOperation
val indexes: MutableList<FirExpression> = mutableListOf()
var calleeReference: FirReference = FirStubReference
override fun build(): FirArraySetCall {
return FirArraySetCallImpl(
source,
annotations,
safe,
typeArguments,
explicitReceiver,
dispatchReceiver,
extensionReceiver,
calleeReference,
argumentList,
rValue,
assignCall,
setGetBlock,
operation,
indexes,
calleeReference,
)
}
@@ -7,13 +7,11 @@ package org.jetbrains.kotlin.fir.expressions.impl
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirArgumentList
import org.jetbrains.kotlin.fir.expressions.FirArraySetCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirOperation
import org.jetbrains.kotlin.fir.expressions.impl.FirModifiableQualifiedAccess
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.visitors.*
/*
@@ -24,97 +22,27 @@ import org.jetbrains.kotlin.fir.visitors.*
internal class FirArraySetCallImpl(
override val source: FirSourceElement?,
override val annotations: MutableList<FirAnnotationCall>,
override var safe: Boolean,
override val typeArguments: MutableList<FirTypeProjection>,
override var explicitReceiver: FirExpression?,
override var dispatchReceiver: FirExpression,
override var extensionReceiver: FirExpression,
override var calleeReference: FirReference,
override var argumentList: FirArgumentList,
override var rValue: FirExpression,
override var assignCall: FirFunctionCall,
override var setGetBlock: FirBlock,
override val operation: FirOperation,
override val indexes: MutableList<FirExpression>,
) : FirArraySetCall(), FirModifiableQualifiedAccess {
override var lValue: FirReference
get() = calleeReference
set(value) {
calleeReference = value
}
override var calleeReference: FirReference,
) : FirArraySetCall() {
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
annotations.forEach { it.accept(visitor, data) }
typeArguments.forEach { it.accept(visitor, data) }
explicitReceiver?.accept(visitor, data)
if (dispatchReceiver !== explicitReceiver) {
dispatchReceiver.accept(visitor, data)
}
if (extensionReceiver !== explicitReceiver && extensionReceiver !== dispatchReceiver) {
extensionReceiver.accept(visitor, data)
}
assignCall.accept(visitor, data)
setGetBlock.accept(visitor, data)
calleeReference.accept(visitor, data)
argumentList.accept(visitor, data)
rValue.accept(visitor, data)
indexes.forEach { it.accept(visitor, data) }
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirArraySetCallImpl {
annotations.transformInplace(transformer, data)
transformTypeArguments(transformer, data)
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
if (dispatchReceiver !== explicitReceiver) {
dispatchReceiver = dispatchReceiver.transformSingle(transformer, data)
}
if (extensionReceiver !== explicitReceiver && extensionReceiver !== dispatchReceiver) {
extensionReceiver = extensionReceiver.transformSingle(transformer, data)
}
transformCalleeReference(transformer, data)
argumentList = argumentList.transformSingle(transformer, data)
transformRValue(transformer, data)
transformIndexes(transformer, data)
return this
}
override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirArraySetCallImpl {
typeArguments.transformInplace(transformer, data)
return this
}
override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirArraySetCallImpl {
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
return this
}
override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirArraySetCallImpl {
dispatchReceiver = dispatchReceiver.transformSingle(transformer, data)
return this
}
override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirArraySetCallImpl {
extensionReceiver = extensionReceiver.transformSingle(transformer, data)
return this
}
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirArraySetCallImpl {
assignCall = assignCall.transformSingle(transformer, data)
setGetBlock = setGetBlock.transformSingle(transformer, data)
calleeReference = calleeReference.transformSingle(transformer, data)
return this
}
override fun <D> transformRValue(transformer: FirTransformer<D>, data: D): FirArraySetCallImpl {
rValue = rValue.transformSingle(transformer, data)
return this
}
override fun <D> transformIndexes(transformer: FirTransformer<D>, data: D): FirArraySetCallImpl {
indexes.transformInplace(transformer, data)
return this
}
override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>) {
typeArguments.clear()
typeArguments.addAll(newTypeArguments)
}
override fun replaceArgumentList(newArgumentList: FirArgumentList) {
argumentList = newArgumentList
override fun replaceCalleeReference(newCalleeReference: FirReference) {
calleeReference = newCalleeReference
}
}
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.Variance
@@ -1000,12 +999,9 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
override fun visitArraySetCall(arraySetCall: FirArraySetCall) {
arraySetCall.annotations.renderAnnotations()
visitQualifiedAccess(arraySetCall)
arraySetCall.lValue.accept(this)
print("[")
arraySetCall.indexes.renderSeparated()
print("] ")
visitAssignment(arraySetCall.operation, arraySetCall.rValue)
print("ArraySet:[")
arraySetCall.assignCall.accept(this)
print("]")
}
override fun visitFunctionCall(functionCall: FirFunctionCall) {
@@ -112,9 +112,8 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
}
builder(arraySetCall) {
parents += qualifiedAccessBuilder
defaultFalse("safe")
defaultNoReceivers()
default("calleeReference", "FirStubReference")
useTypes(stubReferenceType)
}
builder(callableReferenceAccess) {
@@ -89,7 +89,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val checkNotNullCall = element("CheckNotNullCall", Expression, expression, call, resolvable)
val arrayOfCall = element("ArrayOfCall", Expression, expression, call)
val arraySetCall = element("ArraySetCall", Expression, qualifiedAccess, call)
val arraySetCall = element("ArraySetCall", Expression, statement)
val classReferenceExpression = element("ClassReferenceExpression", Expression, expression)
val errorExpression = element("ErrorExpression", Expression, expression, diagnosticHolder)
val errorFunction = element("ErrorFunction", Declaration, function, diagnosticHolder)
@@ -86,14 +86,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
isMutable("safe")
}
impl(arraySetCall) {
parents += modifiableQualifiedAccess
default("lValue") {
value = "calleeReference"
customSetter = "calleeReference = value"
}
}
impl(callableReferenceAccess) {
parents += modifiableQualifiedAccess
}
@@ -396,10 +396,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
}
arraySetCall.configure {
+field("rValue", expression).withTransform()
+field("assignCall", functionCall)
+field("setGetBlock", block)
+field("operation", operationType)
+field("lValue", reference)
+fieldList("indexes", expression).withTransform()
+field("calleeReference", reference, withReplace = true)
}
classReferenceExpression.configure {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
val s = IntArray(1)
s[0] = 5
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
operator fun ArrayList<String>.get(index1: Int, index2: Int) = this[index1 + index2]
operator fun ArrayList<String>.set(index1: Int, index2: Int, elem: String) {
+1 -1
View File
@@ -1,4 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
fun box () : String {
val s = ArrayList<String>()
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
operator fun IntArray.set(index: Long, elem: Int) { this[index.toInt()] = elem }
operator fun IntArray.get(index: Long) = this[index.toInt()]
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
val array = arrayOf(doubleArrayOf(-1.0))
for (node in array) {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
operator fun <K, V> MutableMap<K, V>.set(key : K, value : V) = put(key, value)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
class Host(var value: String) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class X {
var result: String = "fail"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import Host.x
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
object A {
operator fun get(i: Int) = 1
operator fun set(i: Int, j: Int) {}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
fun box(): String {
val l = ArrayList<Int>()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
var result = "fail"
private operator fun X.get(name: String) = name + "K"
@@ -20,7 +20,7 @@ object MismatchingTypes {
fun testMismatchingTypes() {
<!INAPPLICABLE_CANDIDATE!>++MismatchingTypes[0]<!>
<!INAPPLICABLE_CANDIDATE!>MismatchingTypes[0]++<!>
MismatchingTypes[0] += 1
<!UNRESOLVED_REFERENCE!>MismatchingTypes[0] += 1<!>
}
object MismatchingArities1 {
@@ -36,10 +36,10 @@ object MismatchingArities2 {
fun testMismatchingArities() {
<!INAPPLICABLE_CANDIDATE!>++MismatchingArities1[0]<!>
<!INAPPLICABLE_CANDIDATE!>MismatchingArities1[0]++<!>
MismatchingArities1[0] += 1
<!UNRESOLVED_REFERENCE!>MismatchingArities1[0] += 1<!>
<!UNRESOLVED_REFERENCE!>++<!><!INAPPLICABLE_CANDIDATE!>MismatchingArities2[0]<!>
<!INAPPLICABLE_CANDIDATE!>MismatchingArities2[0]<!><!UNRESOLVED_REFERENCE!>++<!>
MismatchingArities2[0] += 1
<!UNRESOLVED_REFERENCE!><!INAPPLICABLE_CANDIDATE!>MismatchingArities2[0]<!> += 1<!>
}
@@ -16,5 +16,5 @@ fun test() {
val c = C()
c[0] += ""
var c1 = C1()
c1[0] += ""
<!AMBIGUITY!>c1[0] += ""<!>
}
@@ -13,7 +13,7 @@ operator fun Int.set(s: Int, x: String = "", z: Int) {
fun main() {
<!INAPPLICABLE_CANDIDATE!>1[2] = 1<!>
1.set(2, z = 1)
1[2] += 1
<!UNRESOLVED_REFERENCE!>1[2] += 1<!>
1.<!INAPPLICABLE_CANDIDATE!>set<!>(2, 1)
}
@@ -46,16 +46,38 @@ FILE fqName:<root> fileName:/arrayAugmentedAssignment1.kt
BLOCK_BODY
VAR name:x type:kotlin.IntArray [var]
CALL 'public final fun foo (): kotlin.IntArray declared in <root>' type=kotlin.IntArray origin=null
ERROR_CALL 'FirArraySetCall (resolve isn't supported yet)' type=kotlin.Unit
BLOCK type=kotlin.Unit origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.IntArray [val]
GET_VAR 'var x: kotlin.IntArray [var] declared in <root>.testVariable' type=kotlin.IntArray origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val]
CONST Int type=kotlin.Int value=0
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_0: kotlin.IntArray [val] declared in <root>.testVariable' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.testVariable' type=kotlin.Int origin=null
value: CALL 'public final fun plus (other: kotlin.Int): 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_0: kotlin.IntArray [val] declared in <root>.testVariable' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.testVariable' type=kotlin.Int origin=null
other: CONST Int type=kotlin.Int value=1
FUN name:testCall visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.IntArray [val]
CALL 'public final fun foo (): kotlin.IntArray declared in <root>' type=kotlin.IntArray origin=null
ERROR_CALL 'FirArraySetCall (resolve isn't supported yet)' type=kotlin.Unit
BLOCK type=kotlin.Unit origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.IntArray [val]
CALL 'public final fun foo (): kotlin.IntArray declared in <root>' type=kotlin.IntArray origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.Int [val]
CALL 'public final fun bar (): kotlin.Int declared in <root>' 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_2: kotlin.IntArray [val] declared in <root>.testCall' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_3: kotlin.Int [val] declared in <root>.testCall' type=kotlin.Int origin=null
value: CALL 'public final fun times (other: kotlin.Int): 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_2: kotlin.IntArray [val] declared in <root>.testCall' type=kotlin.IntArray origin=null
index: GET_VAR 'val tmp_3: kotlin.Int [val] declared in <root>.testCall' type=kotlin.Int origin=null
other: CONST Int type=kotlin.Int value=2
FUN name:testMember visibility:public modality:FINAL <> (c:<root>.C) returnType:kotlin.Unit
VALUE_PARAMETER name:c index:0 type:<root>.C
BLOCK_BODY
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val]
VAR IR_TEMPORARY_VARIABLE name:tmp_4 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: CALL 'public final fun <get-x> (): kotlin.IntArray declared in <root>.C' type=kotlin.IntArray origin=GET_PROPERTY
$this: GET_VAR 'c: <root>.C declared in <root>.testMember' type=<root>.C origin=null
@@ -65,5 +87,5 @@ FILE fqName:<root> fileName:/arrayAugmentedAssignment1.kt
$this: GET_VAR 'c: <root>.C declared in <root>.testMember' type=<root>.C origin=null
index: CONST Int type=kotlin.Int value=0
value: 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>.testMember' type=kotlin.Int origin=null
GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.testMember' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_4: kotlin.Int [val] declared in <root>.testMember' type=kotlin.Int origin=null
GET_VAR 'val tmp_4: kotlin.Int [val] declared in <root>.testMember' type=kotlin.Int origin=null
@@ -41,4 +41,17 @@ FILE fqName:<root> fileName:/arrayAugmentedAssignment2.kt
$receiver: VALUE_PARAMETER name:<this> type:<root>.IB
VALUE_PARAMETER name:a index:0 type:<root>.IA
BLOCK_BODY
ERROR_CALL 'FirArraySetCall (resolve isn't supported yet)' type=kotlin.Unit
BLOCK type=kotlin.Unit origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.IA [val]
GET_VAR 'a: <root>.IA declared in <root>.test' type=<root>.IA origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.String [val]
CONST String type=kotlin.String value=""
CALL 'public abstract fun set (index: kotlin.String, value: kotlin.Int): kotlin.Unit [operator] declared in <root>.IB' type=kotlin.Unit origin=null
$this: GET_VAR '<this>: <root>.IB declared in <root>.test' type=<root>.IB origin=null
$receiver: GET_VAR 'val tmp_0: <root>.IA [val] declared in <root>.test' type=<root>.IA origin=null
index: GET_VAR 'val tmp_1: kotlin.String [val] declared in <root>.test' type=kotlin.String origin=null
value: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public abstract fun get (index: kotlin.String): kotlin.Int [operator] declared in <root>.IA' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_0: <root>.IA [val] declared in <root>.test' type=<root>.IA origin=null
index: GET_VAR 'val tmp_1: kotlin.String [val] declared in <root>.test' type=kotlin.String origin=null
other: CONST Int type=kotlin.Int value=42
@@ -111,7 +111,19 @@ FILE fqName:<root> fileName:/caoWithAdaptationForSam.kt
FUN name:test3 visibility:public modality:FINAL <> (fn:kotlin.Function1<kotlin.Int, kotlin.Unit>) returnType:kotlin.Unit
VALUE_PARAMETER name:fn index:0 type:kotlin.Function1<kotlin.Int, kotlin.Unit>
BLOCK_BODY
ERROR_CALL 'FirArraySetCall (resolve isn't supported yet)' type=kotlin.Unit
BLOCK type=kotlin.Unit origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.A [val]
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.test3' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
CALL 'public final fun set (i: <root>.IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in <root>' type=kotlin.Unit origin=null
$receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test3' type=<root>.A origin=null
i: GET_VAR 'val tmp_1: kotlin.Function1<kotlin.Int, kotlin.Unit> [val] declared in <root>.test3' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
newValue: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun get (i: <root>.IFoo): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=null
$receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test3' type=<root>.A origin=null
i: GET_VAR 'val tmp_1: kotlin.Function1<kotlin.Int, kotlin.Unit> [val] declared in <root>.test3' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
other: CONST Int type=kotlin.Int value=1
FUN name:test4 visibility:public modality:FINAL <> (fn:kotlin.Function1<kotlin.Int, kotlin.Unit>) returnType:kotlin.Unit
VALUE_PARAMETER name:fn index:0 type:kotlin.Function1<kotlin.Int, kotlin.Unit>
BLOCK_BODY
@@ -120,13 +132,40 @@ FILE fqName:<root> fileName:/caoWithAdaptationForSam.kt
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=<root>.IFoo
GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.test4' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
then: BLOCK type=kotlin.Unit origin=null
ERROR_CALL 'FirArraySetCall (resolve isn't supported yet)' type=kotlin.Unit
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:<root>.A [val]
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:<root>.IFoo [val]
TYPE_OP type=<root>.IFoo origin=IMPLICIT_CAST typeOperand=<root>.IFoo
GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.test4' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
CALL 'public final fun set (i: <root>.IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in <root>' type=kotlin.Unit origin=null
$receiver: GET_VAR 'val tmp_2: <root>.A [val] declared in <root>.test4' type=<root>.A origin=null
i: TYPE_OP type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<kotlin.Int, kotlin.Unit>
GET_VAR 'val tmp_3: <root>.IFoo [val] declared in <root>.test4' type=<root>.IFoo origin=null
newValue: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun get (i: <root>.IFoo): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=null
$receiver: GET_VAR 'val tmp_2: <root>.A [val] declared in <root>.test4' type=<root>.A origin=null
i: TYPE_OP type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<kotlin.Int, kotlin.Unit>
GET_VAR 'val tmp_3: <root>.IFoo [val] declared in <root>.test4' type=<root>.IFoo origin=null
other: CONST Int type=kotlin.Int value=1
FUN name:test5 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit
VALUE_PARAMETER name:a index:0 type:kotlin.Any
BLOCK_BODY
TYPE_OP type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=CAST typeOperand=kotlin.Function1<kotlin.Int, kotlin.Unit>
GET_VAR 'a: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null
ERROR_CALL 'FirArraySetCall (resolve isn't supported yet)' type=kotlin.Unit
BLOCK type=kotlin.Unit origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:<root>.A [val]
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
TYPE_OP type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<kotlin.Int, kotlin.Unit>
GET_VAR 'a: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null
CALL 'public final fun set (i: <root>.IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in <root>' type=kotlin.Unit origin=null
$receiver: GET_VAR 'val tmp_4: <root>.A [val] declared in <root>.test5' type=<root>.A origin=null
i: GET_VAR 'val tmp_5: kotlin.Function1<kotlin.Int, kotlin.Unit> [val] declared in <root>.test5' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
newValue: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun get (i: <root>.IFoo): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=null
$receiver: GET_VAR 'val tmp_4: <root>.A [val] declared in <root>.test5' type=<root>.A origin=null
i: GET_VAR 'val tmp_5: kotlin.Function1<kotlin.Int, kotlin.Unit> [val] declared in <root>.test5' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
other: CONST Int type=kotlin.Int value=1
FUN name:test6 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit
VALUE_PARAMETER name:a index:0 type:kotlin.Any
BLOCK_BODY
@@ -135,4 +174,17 @@ FILE fqName:<root> fileName:/caoWithAdaptationForSam.kt
TYPE_OP type=<root>.IFoo origin=CAST typeOperand=<root>.IFoo
TYPE_OP type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<kotlin.Int, kotlin.Unit>
GET_VAR 'a: kotlin.Any declared in <root>.test6' type=kotlin.Any origin=null
ERROR_CALL 'FirArraySetCall (resolve isn't supported yet)' type=kotlin.Unit
BLOCK type=kotlin.Unit origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:<root>.A [val]
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
TYPE_OP type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<kotlin.Int, kotlin.Unit>
GET_VAR 'a: kotlin.Any declared in <root>.test6' type=kotlin.Any origin=null
CALL 'public final fun set (i: <root>.IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in <root>' type=kotlin.Unit origin=null
$receiver: GET_VAR 'val tmp_6: <root>.A [val] declared in <root>.test6' type=<root>.A origin=null
i: GET_VAR 'val tmp_7: kotlin.Function1<kotlin.Int, kotlin.Unit> [val] declared in <root>.test6' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
newValue: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun get (i: <root>.IFoo): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=null
$receiver: GET_VAR 'val tmp_6: <root>.A [val] declared in <root>.test6' type=<root>.A origin=null
i: GET_VAR 'val tmp_7: kotlin.Function1<kotlin.Int, kotlin.Unit> [val] declared in <root>.test6' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
other: CONST Int type=kotlin.Int value=1
+18 -1
View File
@@ -59,4 +59,21 @@ FILE fqName:<root> fileName:/kt28456.kt
FUN name:testCompoundAssignment visibility:public modality:FINAL <> (a:<root>.A) returnType:kotlin.Unit
VALUE_PARAMETER name:a index:0 type:<root>.A
BLOCK_BODY
ERROR_CALL 'FirArraySetCall (resolve isn't supported yet)' type=kotlin.Unit
BLOCK type=kotlin.Unit origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:<root>.A [val]
GET_VAR 'a: <root>.A declared in <root>.testCompoundAssignment' type=<root>.A origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Int [val]
CONST Int type=kotlin.Int value=1
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.Int [val]
CONST Int type=kotlin.Int value=2
CALL 'public final fun set (i: kotlin.Int, j: kotlin.Int, v: kotlin.Int): kotlin.Unit [operator] declared in <root>' type=kotlin.Unit origin=null
$receiver: GET_VAR 'val tmp_1: <root>.A [val] declared in <root>.testCompoundAssignment' type=<root>.A origin=null
i: GET_VAR 'val tmp_2: kotlin.Int [val] declared in <root>.testCompoundAssignment' type=kotlin.Int origin=null
j: GET_VAR 'val tmp_3: kotlin.Int [val] declared in <root>.testCompoundAssignment' type=kotlin.Int origin=null
v: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun get (vararg xs: kotlin.Int): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=null
$receiver: GET_VAR 'val tmp_1: <root>.A [val] declared in <root>.testCompoundAssignment' type=<root>.A origin=null
xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
GET_VAR 'val tmp_2: kotlin.Int [val] declared in <root>.testCompoundAssignment' type=kotlin.Int origin=null
GET_VAR 'val tmp_3: kotlin.Int [val] declared in <root>.testCompoundAssignment' type=kotlin.Int origin=null
other: CONST Int type=kotlin.Int value=10
+19 -4
View File
@@ -26,11 +26,26 @@ FILE fqName:<root> fileName:/lambdaInCAO.kt
FUN name:test2 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit
VALUE_PARAMETER name:a index:0 type:kotlin.Any
BLOCK_BODY
ERROR_CALL 'FirArraySetCall (resolve isn't supported yet)' type=kotlin.Unit
BLOCK type=kotlin.Unit origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Any [val]
GET_VAR 'a: kotlin.Any declared in <root>.test2' type=kotlin.Any origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Function0<kotlin.Unit> [val]
FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
CALL 'public final fun set (index: kotlin.Function0<kotlin.Unit>, value: kotlin.Int): kotlin.Unit [operator] declared in <root>' type=kotlin.Unit origin=null
$receiver: GET_VAR 'val tmp_0: kotlin.Any [val] declared in <root>.test2' type=kotlin.Any origin=null
index: GET_VAR 'val tmp_1: kotlin.Function0<kotlin.Unit> [val] declared in <root>.test2' type=kotlin.Function0<kotlin.Unit> origin=null
value: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun get (index: kotlin.Function0<kotlin.Unit>): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=null
$receiver: GET_VAR 'val tmp_0: kotlin.Any [val] declared in <root>.test2' type=kotlin.Any origin=null
index: GET_VAR 'val tmp_1: kotlin.Function0<kotlin.Unit> [val] declared in <root>.test2' type=kotlin.Function0<kotlin.Unit> origin=null
other: CONST Int type=kotlin.Int value=42
FUN name:test3 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit
VALUE_PARAMETER name:a index:0 type:kotlin.Any
BLOCK_BODY
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val]
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Int [val]
CALL 'public final fun get (index: kotlin.Function0<kotlin.Unit>): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=null
$receiver: GET_VAR 'a: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null
index: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
@@ -44,5 +59,5 @@ FILE fqName:<root> fileName:/lambdaInCAO.kt
BLOCK_BODY
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
value: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.test3' type=kotlin.Int origin=null
GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.test3' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_2: kotlin.Int [val] declared in <root>.test3' type=kotlin.Int origin=null
GET_VAR 'val tmp_2: kotlin.Int [val] declared in <root>.test3' type=kotlin.Int origin=null