diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index a036a3a370c..ceff261f811 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -16175,18 +16175,48 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("arrayAccessCompositeOperators.kt") + public void testArrayAccessCompositeOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessCompositeOperators.kt"); + } + + @Test + @TestMetadata("arrayAccessOperators.kt") + public void testArrayAccessOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessOperators.kt"); + } + + @Test + @TestMetadata("compoundAssignmentOperators.kt") + public void testCompoundAssignmentOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/compoundAssignmentOperators.kt"); + } + @Test @TestMetadata("contextAndExtensionSameName.kt") public void testContextAndExtensionSameName() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/contextAndExtensionSameName.kt"); } + @Test + @TestMetadata("delegatedPropertiesOperators.kt") + public void testDelegatedPropertiesOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/delegatedPropertiesOperators.kt"); + } + @Test @TestMetadata("inferGenericPropertyType.kt") public void testInferGenericPropertyType() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/inferGenericPropertyType.kt"); } + @Test + @TestMetadata("iteratorOperator.kt") + public void testIteratorOperator() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/iteratorOperator.kt"); + } + @Test @TestMetadata("localDeclaration.kt") public void testLocalDeclaration() throws Exception { @@ -16229,6 +16259,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/this.kt"); } + @Test + @TestMetadata("unaryOperators.kt") + public void testUnaryOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/unaryOperators.kt"); + } + @Test @TestMetadata("useFromAnotherModule.kt") public void testUseFromAnotherModule() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java index 9a799428b02..bbb7182c889 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java @@ -751,18 +751,42 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irText/declarations/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("arrayAccessCompositeOperators.kt") + public void testArrayAccessCompositeOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.kt"); + } + + @Test + @TestMetadata("arrayAccessOperators.kt") + public void testArrayAccessOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.kt"); + } + @Test @TestMetadata("class.kt") public void testClass() throws Exception { runTest("compiler/testData/ir/irText/declarations/contextReceivers/class.kt"); } + @Test + @TestMetadata("compoundAssignmentOperators.kt") + public void testCompoundAssignmentOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt"); + } + @Test @TestMetadata("contextualPrimaryConstructorWithParams.kt") public void testContextualPrimaryConstructorWithParams() throws Exception { runTest("compiler/testData/ir/irText/declarations/contextReceivers/contextualPrimaryConstructorWithParams.kt"); } + @Test + @TestMetadata("delegatedPropertiesOperators.kt") + public void testDelegatedPropertiesOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.kt"); + } + @Test @TestMetadata("function.kt") public void testFunction() throws Exception { @@ -781,6 +805,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/declarations/contextReceivers/genericOuterClass.kt"); } + @Test + @TestMetadata("iteratorOperator.kt") + public void testIteratorOperator() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.kt"); + } + @Test @TestMetadata("lazy.kt") public void testLazy() throws Exception { @@ -823,6 +853,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.kt"); } + @Test + @TestMetadata("unaryOperators.kt") + public void testUnaryOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.kt"); + } + @Nested @TestMetadata("compiler/testData/ir/irText/declarations/contextReceivers/fromKEEP") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessCompositeOperators.kt b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessCompositeOperators.kt new file mode 100644 index 00000000000..6095afc6c43 --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessCompositeOperators.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +data class MyContainer(var i: Int) + +var operationScore = 0 + +context(Int) +operator fun MyContainer.get(index: Int): Int { + operationScore += this@Int + return if (index == 0) i else -1 +} + +context(Int) +operator fun MyContainer.plusAssign(other: MyContainer) { + operationScore += this@Int + i += other.i +} + +context(Int) +operator fun MyContainer.inc(): MyContainer { + operationScore += this@Int + return MyContainer(i + 1) +} + +fun box(): String { + var myContainer = MyContainer(0) + with(1) { + myContainer += MyContainer(myContainer++[0]) + } + return if (myContainer.i == 1 && operationScore == 3) "OK" else "fail" +} diff --git a/compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessOperators.kt b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessOperators.kt new file mode 100644 index 00000000000..82231c45f3d --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessOperators.kt @@ -0,0 +1,24 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +data class MyContainer(var s: String) + +context(Int) +operator fun MyContainer.get(index: Int): String? { + return if (index == 0 && this@Int == 42) s else null +} + +context(Int) +operator fun MyContainer.set(index: Int, value: String) { + if (index != 0 || this@Int != 42) return + s = value +} + +fun box(): String { + return with(42) { + val myContainer = MyContainer("fail") + myContainer[0] = "OK" + myContainer[0] ?: "fail" + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/extensionFunctions/contextReceivers/compoundAssignmentOperators.kt b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/compoundAssignmentOperators.kt new file mode 100644 index 00000000000..a415b2281db --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/compoundAssignmentOperators.kt @@ -0,0 +1,67 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +data class Result(var i: Int) + +var operationScore = 0 + +context(Int) +operator fun Result.plus(other: Result): Result { + operationScore += this@Int + return Result(i + other.i) +} + +context(Int) +operator fun Result.plusAssign(other: Result) { + operationScore += this@Int + i += other.i +} + +context(Int) +operator fun Result.minus(other: Result): Result { + operationScore += this@Int + return Result(i - other.i) +} + +context(Int) +operator fun Result.minusAssign(other: Result) { + operationScore += this@Int + i -= other.i +} + +context(Int) +operator fun Result.times(other: Result): Result { + operationScore += this@Int + return Result(i * other.i) +} + +context(Int) +operator fun Result.timesAssign(other: Result) { + operationScore += this@Int + i *= other.i +} + +context(Int) +operator fun Result.div(other: Result): Result { + operationScore += this@Int + return Result(i / other.i) +} + +context(Int) +operator fun Result.divAssign(other: Result) { + operationScore += this@Int + i /= other.i +} + +fun box(): String { + val result = Result(0) + with(1) { + result += (Result(1) + Result(1)) + result -= (Result(1) - Result(0)) + result *= (Result(1) * Result(2)) + result /= (Result(4) / Result(2)) + } + return if (result.i == 1 && operationScore == 8) "OK" else "fail" +} + diff --git a/compiler/testData/codegen/box/extensionFunctions/contextReceivers/delegatedPropertiesOperators.kt b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/delegatedPropertiesOperators.kt new file mode 100644 index 00000000000..b4c91a7f2ed --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/delegatedPropertiesOperators.kt @@ -0,0 +1,36 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_STDLIB + +import kotlin.reflect.KProperty + +var operationScore = 0 + +class Delegate { + var delegateValue = "fail" + + context(Int) + operator fun getValue(thisRef: Any?, property: KProperty<*>): String { + operationScore += this@Int + return delegateValue + } + + context(Int) + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { + operationScore += this@Int + delegateValue = value + } +} + +context(Int) +class Result { + var s: String by Delegate() +} + +fun box(): String { + val result = with(1) { Result() } + result.s = "OK" + val returnValue = result.s + return if (operationScore == 2) returnValue else "fail" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/extensionFunctions/contextReceivers/iteratorOperator.kt b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/iteratorOperator.kt new file mode 100644 index 00000000000..49390ed3dff --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/iteratorOperator.kt @@ -0,0 +1,28 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_STDLIB + +data class Counter(var i: Int = 0) + +data class CounterConfig(val max: Int = 10) + +context(CounterConfig) +class CounterIterator(private val counter: Counter) : Iterator { + override fun hasNext() = counter.i < max + override fun next() = counter.i++ +} + +context(CounterConfig) +operator fun Counter.iterator() = with(this@CounterConfig) { CounterIterator(this@Counter) } + + +fun box(): String { + var result = 0 + with(CounterConfig()) { + for (i in Counter()) { + result += i + } + } + return if (result == 45) "OK" else "fail" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/extensionFunctions/contextReceivers/unaryOperators.kt b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/unaryOperators.kt new file mode 100644 index 00000000000..3615e5a32dd --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/unaryOperators.kt @@ -0,0 +1,45 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +data class Result(val i: Int) + +var operationScore = 0 + +context(Int) +operator fun Result.unaryMinus(): Result { + operationScore += this@Int + return Result(-i) +} + +context(Int) +operator fun Result.unaryPlus(): Result { + operationScore += this@Int + return Result(if (i < 0) (-i) else i) +} + +context(Int) +operator fun Result.inc(): Result { + operationScore += this@Int + return Result(i + 1) +} + +context(Int) +operator fun Result.dec(): Result { + operationScore += this@Int + return Result(i - 1) +} + +fun box(): String { + var result = Result(0) + with(1) { + result++ + result++ + (-result) + +result + result-- + } + return if (result.i == 1 && operationScore == 5) "OK" else "fail" +} + + diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.ir.txt new file mode 100644 index 00000000000..6bebca16ad1 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.ir.txt @@ -0,0 +1,219 @@ +FILE fqName: fileName:/arrayAccessCompositeOperators.kt + CLASS CLASS name:MyContainer modality:FINAL visibility:public [data] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.MyContainer + CONSTRUCTOR visibility:public <> (i:kotlin.Int) returnType:.MyContainer [primary] + VALUE_PARAMETER name:i index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:MyContainer modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' + PROPERTY name:i visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private + EXPRESSION_BODY + GET_VAR 'i: kotlin.Int declared in .MyContainer.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.MyContainer) returnType:kotlin.Int + correspondingProperty: PROPERTY name:i visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.MyContainer + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .MyContainer' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.' type=.MyContainer origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.MyContainer, :kotlin.Int) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:i visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Unit origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.' type=.MyContainer origin=null + value: GET_VAR ': kotlin.Int declared in .MyContainer.' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:.MyContainer) returnType:kotlin.Int [operator] + $this: VALUE_PARAMETER name: type:.MyContainer + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.Int [operator] declared in .MyContainer' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.component1' type=.MyContainer origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:.MyContainer, i:kotlin.Int) returnType:.MyContainer + $this: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name:i index:0 type:kotlin.Int + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.copy' type=.MyContainer origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (i: kotlin.Int): .MyContainer declared in .MyContainer' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .MyContainer' type=.MyContainer origin=null + i: GET_VAR 'i: kotlin.Int declared in .MyContainer.copy' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:.MyContainer) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.MyContainer + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .MyContainer' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="MyContainer(" + CONST String type=kotlin.String value="i=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.toString' type=.MyContainer origin=null + CONST String type=kotlin.String value=")" + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.MyContainer) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.MyContainer + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .MyContainer' + CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.hashCode' type=.MyContainer origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.MyContainer, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': .MyContainer declared in .MyContainer.equals' type=.MyContainer origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in .MyContainer.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .MyContainer' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=.MyContainer + GET_VAR 'other: kotlin.Any? declared in .MyContainer.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .MyContainer' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.MyContainer [val] + TYPE_OP type=.MyContainer origin=CAST typeOperand=.MyContainer + GET_VAR 'other: kotlin.Any? declared in .MyContainer.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.equals' type=.MyContainer origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR 'val tmp_0: .MyContainer [val] declared in .MyContainer.equals' type=.MyContainer origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .MyContainer' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .MyContainer' + CONST Boolean type=kotlin.Boolean value=true + PROPERTY name:operationScore visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static] + EXPRESSION_BODY + CONST Int type=kotlin.Int value=0 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int + correspondingProperty: PROPERTY name:operationScore visibility:public modality:FINAL [var] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static]' type=kotlin.Int origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> (:kotlin.Int) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:operationScore visibility:public modality:FINAL [var] + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static]' type=kotlin.Unit origin=null + value: GET_VAR ': kotlin.Int declared in .' type=kotlin.Int origin=null + FUN name:get visibility:public modality:FINAL <> ($receiver:.MyContainer, :kotlin.Int, index:kotlin.Int) returnType:kotlin.Int [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:index index:1 type:kotlin.Int + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .get' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun get (: kotlin.Int, index: kotlin.Int): kotlin.Int [operator] declared in ' + WHEN type=kotlin.Int origin=IF + 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 'index: kotlin.Int declared in .get' type=kotlin.Int origin=null + arg1: CONST Int type=kotlin.Int value=0 + then: CALL 'public final fun (): kotlin.Int declared in .MyContainer' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .MyContainer declared in .get' type=.MyContainer origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Int type=kotlin.Int value=-1 + FUN name:plusAssign visibility:public modality:FINAL <> ($receiver:.MyContainer, :kotlin.Int, other:.MyContainer) returnType:kotlin.Unit [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:other index:1 type:.MyContainer + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .plusAssign' type=kotlin.Int origin=null + BLOCK type=kotlin.Unit origin=PLUSEQ + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:.MyContainer [val] + GET_VAR ': .MyContainer declared in .plusAssign' type=.MyContainer origin=null + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in .MyContainer' type=kotlin.Unit origin=PLUSEQ + $this: GET_VAR 'val tmp_1: .MyContainer [val] declared in .plusAssign' type=.MyContainer origin=null + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in .MyContainer' type=kotlin.Int origin=PLUSEQ + $this: GET_VAR 'val tmp_1: .MyContainer [val] declared in .plusAssign' type=.MyContainer origin=null + other: CALL 'public final fun (): kotlin.Int declared in .MyContainer' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'other: .MyContainer declared in .plusAssign' type=.MyContainer origin=null + FUN name:inc visibility:public modality:FINAL <> ($receiver:.MyContainer, :kotlin.Int) returnType:.MyContainer [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .inc' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun inc (: kotlin.Int): .MyContainer [operator] declared in ' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .MyContainer' type=.MyContainer origin=null + i: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS + $this: CALL 'public final fun (): kotlin.Int declared in .MyContainer' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .MyContainer declared in .inc' type=.MyContainer origin=null + other: CONST Int type=kotlin.Int value=1 + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + VAR name:myContainer type:.MyContainer [var] + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .MyContainer' type=.MyContainer origin=null + i: CONST Int type=kotlin.Int value=0 + CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.Unit origin=null + : kotlin.Int + : kotlin.Unit + receiver: CONST Int type=kotlin.Int value=1 + block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:kotlin.Int) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER name:$this$with type:kotlin.Int + BLOCK_BODY + CALL 'public final fun plusAssign (: kotlin.Int, other: .MyContainer): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=PLUSEQ + $receiver: GET_VAR 'var myContainer: .MyContainer [var] declared in .box' type=.MyContainer origin=PLUSEQ + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + other: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .MyContainer' type=.MyContainer origin=null + i: CALL 'public final fun get (: kotlin.Int, index: kotlin.Int): kotlin.Int [operator] declared in ' type=kotlin.Int origin=GET_ARRAY_ELEMENT + $receiver: BLOCK type=.MyContainer origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:.MyContainer [val] + GET_VAR 'var myContainer: .MyContainer [var] declared in .box' type=.MyContainer origin=POSTFIX_INCR + SET_VAR 'var myContainer: .MyContainer [var] declared in .box' type=kotlin.Unit origin=POSTFIX_INCR + CALL 'public final fun inc (: kotlin.Int): .MyContainer [operator] declared in ' type=.MyContainer origin=POSTFIX_INCR + $receiver: GET_VAR 'val tmp_2: .MyContainer [val] declared in .box.' type=.MyContainer origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + GET_VAR 'val tmp_2: .MyContainer [val] declared in .box.' type=.MyContainer origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + index: CONST Int type=kotlin.Int value=0 + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + WHEN type=kotlin.String origin=IF + BRANCH + if: WHEN type=kotlin.Boolean origin=ANDAND + 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: CALL 'public final fun (): kotlin.Int declared in .MyContainer' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'var myContainer: .MyContainer [var] declared in .box' type=.MyContainer origin=null + arg1: CONST Int type=kotlin.Int value=1 + then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=GET_PROPERTY + arg1: CONST Int type=kotlin.Int value=3 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Boolean type=kotlin.Boolean value=false + then: CONST String type=kotlin.String value="OK" + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST String type=kotlin.String value="fail" diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.kt b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.kt new file mode 100644 index 00000000000..6095afc6c43 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +data class MyContainer(var i: Int) + +var operationScore = 0 + +context(Int) +operator fun MyContainer.get(index: Int): Int { + operationScore += this@Int + return if (index == 0) i else -1 +} + +context(Int) +operator fun MyContainer.plusAssign(other: MyContainer) { + operationScore += this@Int + i += other.i +} + +context(Int) +operator fun MyContainer.inc(): MyContainer { + operationScore += this@Int + return MyContainer(i + 1) +} + +fun box(): String { + var myContainer = MyContainer(0) + with(1) { + myContainer += MyContainer(myContainer++[0]) + } + return if (myContainer.i == 1 && operationScore == 3) "OK" else "fail" +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.kt.txt new file mode 100644 index 00000000000..744f010d431 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.kt.txt @@ -0,0 +1,94 @@ +data class MyContainer { + constructor(i: Int) /* primary */ { + super/*Any*/() + /* () */ + + } + + var i: Int + field = i + get + set + + operator fun component1(): Int { + return .#i + } + + fun copy(i: Int = .#i): MyContainer { + return MyContainer(i = i) + } + + override fun toString(): String { + return "MyContainer(" + "i=" + .#i + ")" + } + + override fun hashCode(): Int { + return .#i.hashCode() + } + + override operator fun equals(other: Any?): Boolean { + when { + EQEQEQ(arg0 = , arg1 = other) -> return true + } + when { + other !is MyContainer -> return false + } + val tmp0_other_with_cast: MyContainer = other as MyContainer + when { + EQEQ(arg0 = .#i, arg1 = tmp0_other_with_cast.#i).not() -> return false + } + return true + } + +} + +var operationScore: Int + field = 0 + get + set + +operator fun MyContainer.get(: Int, index: Int): Int { + { // BLOCK + ( = ().plus(other = )) + } + return when { + EQEQ(arg0 = index, arg1 = 0) -> .() + else -> -1 + } +} + +operator fun MyContainer.plusAssign(: Int, other: MyContainer) { + { // BLOCK + ( = ().plus(other = )) + } + { // BLOCK + val tmp0_this: MyContainer = + tmp0_this.( = tmp0_this.().plus(other = other.())) + } +} + +operator fun MyContainer.inc(: Int): MyContainer { + { // BLOCK + ( = ().plus(other = )) + } + return MyContainer(i = .().plus(other = 1)) +} + +fun box(): String { + var myContainer: MyContainer = MyContainer(i = 0) + with(receiver = 1, block = local fun Int.() { + myContainer.plusAssign( = $this$with, other = MyContainer(i = { // BLOCK + val tmp0: MyContainer = myContainer + myContainer = tmp0.inc( = $this$with) + tmp0 + }.get( = $this$with, index = 0))) + } +) + return when { + when { + EQEQ(arg0 = myContainer.(), arg1 = 1) -> EQEQ(arg0 = (), arg1 = 3) + else -> false + } -> "OK" + else -> "fail" + } +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.ir.txt new file mode 100644 index 00000000000..12c4dbdf533 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.ir.txt @@ -0,0 +1,185 @@ +FILE fqName: fileName:/arrayAccessOperators.kt + CLASS CLASS name:MyContainer modality:FINAL visibility:public [data] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.MyContainer + CONSTRUCTOR visibility:public <> (s:kotlin.String) returnType:.MyContainer [primary] + VALUE_PARAMETER name:s index:0 type:kotlin.String + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:MyContainer modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' + PROPERTY name:s visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:s type:kotlin.String visibility:private + EXPRESSION_BODY + GET_VAR 's: kotlin.String declared in .MyContainer.' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.MyContainer) returnType:kotlin.String + correspondingProperty: PROPERTY name:s visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.MyContainer + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in .MyContainer' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:s type:kotlin.String visibility:private' type=kotlin.String origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.' type=.MyContainer origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.MyContainer, :kotlin.String) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:s visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name: index:0 type:kotlin.String + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:s type:kotlin.String visibility:private' type=kotlin.Unit origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.' type=.MyContainer origin=null + value: GET_VAR ': kotlin.String declared in .MyContainer.' type=kotlin.String origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:.MyContainer) returnType:kotlin.String [operator] + $this: VALUE_PARAMETER name: type:.MyContainer + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String [operator] declared in .MyContainer' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:s type:kotlin.String visibility:private' type=kotlin.String origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.component1' type=.MyContainer origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:.MyContainer, s:kotlin.String) returnType:.MyContainer + $this: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name:s index:0 type:kotlin.String + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:s type:kotlin.String visibility:private' type=kotlin.String origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.copy' type=.MyContainer origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (s: kotlin.String): .MyContainer declared in .MyContainer' + CONSTRUCTOR_CALL 'public constructor (s: kotlin.String) [primary] declared in .MyContainer' type=.MyContainer origin=null + s: GET_VAR 's: kotlin.String declared in .MyContainer.copy' type=kotlin.String origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:.MyContainer) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.MyContainer + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .MyContainer' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="MyContainer(" + CONST String type=kotlin.String value="s=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:s type:kotlin.String visibility:private' type=kotlin.String origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.toString' type=.MyContainer origin=null + CONST String type=kotlin.String value=")" + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.MyContainer) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.MyContainer + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .MyContainer' + CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.String' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:s type:kotlin.String visibility:private' type=kotlin.String origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.hashCode' type=.MyContainer origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.MyContainer, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': .MyContainer declared in .MyContainer.equals' type=.MyContainer origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in .MyContainer.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .MyContainer' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=.MyContainer + GET_VAR 'other: kotlin.Any? declared in .MyContainer.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .MyContainer' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.MyContainer [val] + TYPE_OP type=.MyContainer origin=CAST typeOperand=.MyContainer + GET_VAR 'other: kotlin.Any? declared in .MyContainer.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:s type:kotlin.String visibility:private' type=kotlin.String origin=null + receiver: GET_VAR ': .MyContainer declared in .MyContainer.equals' type=.MyContainer origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:s type:kotlin.String visibility:private' type=kotlin.String origin=null + receiver: GET_VAR 'val tmp_0: .MyContainer [val] declared in .MyContainer.equals' type=.MyContainer origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .MyContainer' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .MyContainer' + CONST Boolean type=kotlin.Boolean value=true + FUN name:get visibility:public modality:FINAL <> ($receiver:.MyContainer, :kotlin.Int, index:kotlin.Int) returnType:kotlin.String? [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:index index:1 type:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun get (: kotlin.Int, index: kotlin.Int): kotlin.String? [operator] declared in ' + WHEN type=kotlin.String? origin=IF + BRANCH + if: WHEN type=kotlin.Boolean origin=ANDAND + 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 'index: kotlin.Int declared in .get' type=kotlin.Int origin=null + arg1: CONST Int type=kotlin.Int value=0 + then: 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 ': kotlin.Int declared in .get' type=kotlin.Int origin=null + arg1: CONST Int type=kotlin.Int value=42 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Boolean type=kotlin.Boolean value=false + then: CALL 'public final fun (): kotlin.String declared in .MyContainer' type=kotlin.String origin=GET_PROPERTY + $this: GET_VAR ': .MyContainer declared in .get' type=.MyContainer origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null + FUN name:set visibility:public modality:FINAL <> ($receiver:.MyContainer, :kotlin.Int, index:kotlin.Int, value:kotlin.String) returnType:kotlin.Unit [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.MyContainer + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:index index:1 type:kotlin.Int + VALUE_PARAMETER name:value index:2 type:kotlin.String + BLOCK_BODY + WHEN type=kotlin.Unit origin=IF + BRANCH + if: WHEN type=kotlin.Boolean origin=OROR + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_VAR 'index: kotlin.Int declared in .set' type=kotlin.Int origin=null + arg1: CONST Int type=kotlin.Int value=0 + then: CONST Boolean type=kotlin.Boolean value=true + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_VAR ': kotlin.Int declared in .set' type=kotlin.Int origin=null + arg1: CONST Int type=kotlin.Int value=42 + then: RETURN type=kotlin.Nothing from='public final fun set (: kotlin.Int, index: kotlin.Int, value: kotlin.String): kotlin.Unit [operator] declared in ' + GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit + CALL 'public final fun (: kotlin.String): kotlin.Unit declared in .MyContainer' type=kotlin.Unit origin=EQ + $this: GET_VAR ': .MyContainer declared in .set' type=.MyContainer origin=null + : GET_VAR 'value: kotlin.String declared in .set' type=kotlin.String origin=null + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.String origin=null + : kotlin.Int + : kotlin.String + receiver: CONST Int type=kotlin.Int value=42 + block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:kotlin.Int) returnType:kotlin.String + $receiver: VALUE_PARAMETER name:$this$with type:kotlin.Int + BLOCK_BODY + VAR name:myContainer type:.MyContainer [val] + CONSTRUCTOR_CALL 'public constructor (s: kotlin.String) [primary] declared in .MyContainer' type=.MyContainer origin=null + s: CONST String type=kotlin.String value="fail" + CALL 'public final fun set (: kotlin.Int, index: kotlin.Int, value: kotlin.String): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=EQ + $receiver: GET_VAR 'val myContainer: .MyContainer [val] declared in .box.' type=.MyContainer origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + index: CONST Int type=kotlin.Int value=0 + value: CONST String type=kotlin.String value="OK" + RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .box' + BLOCK type=kotlin.String origin=ELVIS + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.String? [val] + CALL 'public final fun get (: kotlin.Int, index: kotlin.Int): kotlin.String? [operator] declared in ' type=kotlin.String? origin=GET_ARRAY_ELEMENT + $receiver: GET_VAR 'val myContainer: .MyContainer [val] declared in .box.' type=.MyContainer origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + index: CONST Int type=kotlin.Int value=0 + WHEN type=kotlin.String 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_1: kotlin.String? [val] declared in .box.' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST String type=kotlin.String value="fail" + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: GET_VAR 'val tmp_1: kotlin.String? [val] declared in .box.' type=kotlin.String? origin=null diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.kt b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.kt new file mode 100644 index 00000000000..82231c45f3d --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.kt @@ -0,0 +1,24 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +data class MyContainer(var s: String) + +context(Int) +operator fun MyContainer.get(index: Int): String? { + return if (index == 0 && this@Int == 42) s else null +} + +context(Int) +operator fun MyContainer.set(index: Int, value: String) { + if (index != 0 || this@Int != 42) return + s = value +} + +fun box(): String { + return with(42) { + val myContainer = MyContainer("fail") + myContainer[0] = "OK" + myContainer[0] ?: "fail" + } +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.kt.txt new file mode 100644 index 00000000000..bd746cf5a95 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.kt.txt @@ -0,0 +1,78 @@ +data class MyContainer { + constructor(s: String) /* primary */ { + super/*Any*/() + /* () */ + + } + + var s: String + field = s + get + set + + operator fun component1(): String { + return .#s + } + + fun copy(s: String = .#s): MyContainer { + return MyContainer(s = s) + } + + override fun toString(): String { + return "MyContainer(" + "s=" + .#s + ")" + } + + override fun hashCode(): Int { + return .#s.hashCode() + } + + override operator fun equals(other: Any?): Boolean { + when { + EQEQEQ(arg0 = , arg1 = other) -> return true + } + when { + other !is MyContainer -> return false + } + val tmp0_other_with_cast: MyContainer = other as MyContainer + when { + EQEQ(arg0 = .#s, arg1 = tmp0_other_with_cast.#s).not() -> return false + } + return true + } + +} + +operator fun MyContainer.get(: Int, index: Int): String? { + return when { + when { + EQEQ(arg0 = index, arg1 = 0) -> EQEQ(arg0 = , arg1 = 42) + else -> false + } -> .() + else -> null + } +} + +operator fun MyContainer.set(: Int, index: Int, value: String) { + when { + when { + EQEQ(arg0 = index, arg1 = 0).not() -> true + else -> EQEQ(arg0 = , arg1 = 42).not() + } -> return Unit + } + .( = value) +} + +fun box(): String { + return with(receiver = 42, block = local fun Int.(): String { + val myContainer: MyContainer = MyContainer(s = "fail") + myContainer.set( = $this$with, index = 0, value = "OK") + return { // BLOCK + val tmp0_elvis_lhs: String? = myContainer.get( = $this$with, index = 0) + when { + EQEQ(arg0 = tmp0_elvis_lhs, arg1 = null) -> "fail" + else -> tmp0_elvis_lhs + } + } + } +) +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.ir.txt new file mode 100644 index 00000000000..43a65e23f56 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.ir.txt @@ -0,0 +1,337 @@ +FILE fqName: fileName:/compoundAssignmentOperators.kt + CLASS CLASS name:Result modality:FINAL visibility:public [data] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Result + CONSTRUCTOR visibility:public <> (i:kotlin.Int) returnType:.Result [primary] + VALUE_PARAMETER name:i index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Result modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' + PROPERTY name:i visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private + EXPRESSION_BODY + GET_VAR 'i: kotlin.Int declared in .Result.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Result) returnType:kotlin.Int + correspondingProperty: PROPERTY name:i visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.Result + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .Result' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.' type=.Result origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Result, :kotlin.Int) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:i visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Unit origin=null + receiver: GET_VAR ': .Result declared in .Result.' type=.Result origin=null + value: GET_VAR ': kotlin.Int declared in .Result.' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:.Result) returnType:kotlin.Int [operator] + $this: VALUE_PARAMETER name: type:.Result + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.Int [operator] declared in .Result' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.component1' type=.Result origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:.Result, i:kotlin.Int) returnType:.Result + $this: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name:i index:0 type:kotlin.Int + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.copy' type=.Result origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (i: kotlin.Int): .Result declared in .Result' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: GET_VAR 'i: kotlin.Int declared in .Result.copy' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Result) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Result + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Result' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="Result(" + CONST String type=kotlin.String value="i=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.toString' type=.Result origin=null + CONST String type=kotlin.String value=")" + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Result) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Result + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Result' + CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.hashCode' type=.Result origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Result, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': .Result declared in .Result.equals' type=.Result origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in .Result.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Result' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=.Result + GET_VAR 'other: kotlin.Any? declared in .Result.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Result' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.Result [val] + TYPE_OP type=.Result origin=CAST typeOperand=.Result + GET_VAR 'other: kotlin.Any? declared in .Result.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.equals' type=.Result origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR 'val tmp_0: .Result [val] declared in .Result.equals' type=.Result origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Result' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Result' + CONST Boolean type=kotlin.Boolean value=true + PROPERTY name:operationScore visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static] + EXPRESSION_BODY + CONST Int type=kotlin.Int value=0 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int + correspondingProperty: PROPERTY name:operationScore visibility:public modality:FINAL [var] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static]' type=kotlin.Int origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> (:kotlin.Int) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:operationScore visibility:public modality:FINAL [var] + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static]' type=kotlin.Unit origin=null + value: GET_VAR ': kotlin.Int declared in .' type=kotlin.Int origin=null + FUN name:plus visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int, other:.Result) returnType:.Result [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:other index:1 type:.Result + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .plus' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun plus (: kotlin.Int, other: .Result): .Result [operator] declared in ' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .plus' type=.Result origin=null + other: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'other: .Result declared in .plus' type=.Result origin=null + FUN name:plusAssign visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int, other:.Result) returnType:kotlin.Unit [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:other index:1 type:.Result + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .plusAssign' type=kotlin.Int origin=null + BLOCK type=kotlin.Unit origin=PLUSEQ + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:.Result [val] + GET_VAR ': .Result declared in .plusAssign' type=.Result origin=null + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in .Result' type=kotlin.Unit origin=PLUSEQ + $this: GET_VAR 'val tmp_1: .Result [val] declared in .plusAssign' type=.Result origin=null + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=PLUSEQ + $this: GET_VAR 'val tmp_1: .Result [val] declared in .plusAssign' type=.Result origin=null + other: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'other: .Result declared in .plusAssign' type=.Result origin=null + FUN name:minus visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int, other:.Result) returnType:.Result [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:other index:1 type:.Result + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .minus' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun minus (: kotlin.Int, other: .Result): .Result [operator] declared in ' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CALL 'public final fun minus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=MINUS + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .minus' type=.Result origin=null + other: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'other: .Result declared in .minus' type=.Result origin=null + FUN name:minusAssign visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int, other:.Result) returnType:kotlin.Unit [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:other index:1 type:.Result + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .minusAssign' type=kotlin.Int origin=null + BLOCK type=kotlin.Unit origin=MINUSEQ + VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:.Result [val] + GET_VAR ': .Result declared in .minusAssign' type=.Result origin=null + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in .Result' type=kotlin.Unit origin=MINUSEQ + $this: GET_VAR 'val tmp_2: .Result [val] declared in .minusAssign' type=.Result origin=null + : CALL 'public final fun minus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=MINUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=MINUSEQ + $this: GET_VAR 'val tmp_2: .Result [val] declared in .minusAssign' type=.Result origin=null + other: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'other: .Result declared in .minusAssign' type=.Result origin=null + FUN name:times visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int, other:.Result) returnType:.Result [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:other index:1 type:.Result + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .times' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun times (: kotlin.Int, other: .Result): .Result [operator] declared in ' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CALL 'public final fun times (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=MUL + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .times' type=.Result origin=null + other: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'other: .Result declared in .times' type=.Result origin=null + FUN name:timesAssign visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int, other:.Result) returnType:kotlin.Unit [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:other index:1 type:.Result + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .timesAssign' type=kotlin.Int origin=null + BLOCK type=kotlin.Unit origin=MULTEQ + VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:.Result [val] + GET_VAR ': .Result declared in .timesAssign' type=.Result origin=null + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in .Result' type=kotlin.Unit origin=MULTEQ + $this: GET_VAR 'val tmp_3: .Result [val] declared in .timesAssign' type=.Result origin=null + : CALL 'public final fun times (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=MULTEQ + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=MULTEQ + $this: GET_VAR 'val tmp_3: .Result [val] declared in .timesAssign' type=.Result origin=null + other: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'other: .Result declared in .timesAssign' type=.Result origin=null + FUN name:div visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int, other:.Result) returnType:.Result [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:other index:1 type:.Result + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .div' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun div (: kotlin.Int, other: .Result): .Result [operator] declared in ' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CALL 'public final fun div (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=DIV + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .div' type=.Result origin=null + other: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'other: .Result declared in .div' type=.Result origin=null + FUN name:divAssign visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int, other:.Result) returnType:kotlin.Unit [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:other index:1 type:.Result + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .divAssign' type=kotlin.Int origin=null + BLOCK type=kotlin.Unit origin=DIVEQ + VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:.Result [val] + GET_VAR ': .Result declared in .divAssign' type=.Result origin=null + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in .Result' type=kotlin.Unit origin=DIVEQ + $this: GET_VAR 'val tmp_4: .Result [val] declared in .divAssign' type=.Result origin=null + : CALL 'public final fun div (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=DIVEQ + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=DIVEQ + $this: GET_VAR 'val tmp_4: .Result [val] declared in .divAssign' type=.Result origin=null + other: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'other: .Result declared in .divAssign' type=.Result origin=null + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + VAR name:result type:.Result [val] + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=0 + CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.Unit origin=null + : kotlin.Int + : kotlin.Unit + receiver: CONST Int type=kotlin.Int value=1 + block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:kotlin.Int) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER name:$this$with type:kotlin.Int + BLOCK_BODY + CALL 'public final fun plusAssign (: kotlin.Int, other: .Result): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=PLUSEQ + $receiver: GET_VAR 'val result: .Result [val] declared in .box' type=.Result origin=PLUSEQ + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + other: CALL 'public final fun plus (: kotlin.Int, other: .Result): .Result [operator] declared in ' type=.Result origin=PLUS + $receiver: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=1 + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + other: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=1 + CALL 'public final fun minusAssign (: kotlin.Int, other: .Result): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=MINUSEQ + $receiver: GET_VAR 'val result: .Result [val] declared in .box' type=.Result origin=MINUSEQ + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + other: CALL 'public final fun minus (: kotlin.Int, other: .Result): .Result [operator] declared in ' type=.Result origin=MINUS + $receiver: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=1 + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + other: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=0 + CALL 'public final fun timesAssign (: kotlin.Int, other: .Result): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=MULTEQ + $receiver: GET_VAR 'val result: .Result [val] declared in .box' type=.Result origin=MULTEQ + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + other: CALL 'public final fun times (: kotlin.Int, other: .Result): .Result [operator] declared in ' type=.Result origin=MUL + $receiver: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=1 + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + other: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=2 + CALL 'public final fun divAssign (: kotlin.Int, other: .Result): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=DIVEQ + $receiver: GET_VAR 'val result: .Result [val] declared in .box' type=.Result origin=DIVEQ + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + other: CALL 'public final fun div (: kotlin.Int, other: .Result): .Result [operator] declared in ' type=.Result origin=DIV + $receiver: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=4 + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + other: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=2 + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + WHEN type=kotlin.String origin=IF + BRANCH + if: WHEN type=kotlin.Boolean origin=ANDAND + 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: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'val result: .Result [val] declared in .box' type=.Result origin=null + arg1: CONST Int type=kotlin.Int value=1 + then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=GET_PROPERTY + arg1: CONST Int type=kotlin.Int value=8 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Boolean type=kotlin.Boolean value=false + then: CONST String type=kotlin.String value="OK" + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST String type=kotlin.String value="fail" diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt b/compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt new file mode 100644 index 00000000000..a415b2281db --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt @@ -0,0 +1,67 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +data class Result(var i: Int) + +var operationScore = 0 + +context(Int) +operator fun Result.plus(other: Result): Result { + operationScore += this@Int + return Result(i + other.i) +} + +context(Int) +operator fun Result.plusAssign(other: Result) { + operationScore += this@Int + i += other.i +} + +context(Int) +operator fun Result.minus(other: Result): Result { + operationScore += this@Int + return Result(i - other.i) +} + +context(Int) +operator fun Result.minusAssign(other: Result) { + operationScore += this@Int + i -= other.i +} + +context(Int) +operator fun Result.times(other: Result): Result { + operationScore += this@Int + return Result(i * other.i) +} + +context(Int) +operator fun Result.timesAssign(other: Result) { + operationScore += this@Int + i *= other.i +} + +context(Int) +operator fun Result.div(other: Result): Result { + operationScore += this@Int + return Result(i / other.i) +} + +context(Int) +operator fun Result.divAssign(other: Result) { + operationScore += this@Int + i /= other.i +} + +fun box(): String { + val result = Result(0) + with(1) { + result += (Result(1) + Result(1)) + result -= (Result(1) - Result(0)) + result *= (Result(1) * Result(2)) + result /= (Result(4) / Result(2)) + } + return if (result.i == 1 && operationScore == 8) "OK" else "fail" +} + diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt.txt new file mode 100644 index 00000000000..258dadf07fb --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt.txt @@ -0,0 +1,134 @@ +data class Result { + constructor(i: Int) /* primary */ { + super/*Any*/() + /* () */ + + } + + var i: Int + field = i + get + set + + operator fun component1(): Int { + return .#i + } + + fun copy(i: Int = .#i): Result { + return Result(i = i) + } + + override fun toString(): String { + return "Result(" + "i=" + .#i + ")" + } + + override fun hashCode(): Int { + return .#i.hashCode() + } + + override operator fun equals(other: Any?): Boolean { + when { + EQEQEQ(arg0 = , arg1 = other) -> return true + } + when { + other !is Result -> return false + } + val tmp0_other_with_cast: Result = other as Result + when { + EQEQ(arg0 = .#i, arg1 = tmp0_other_with_cast.#i).not() -> return false + } + return true + } + +} + +var operationScore: Int + field = 0 + get + set + +operator fun Result.plus(: Int, other: Result): Result { + { // BLOCK + ( = ().plus(other = )) + } + return Result(i = .().plus(other = other.())) +} + +operator fun Result.plusAssign(: Int, other: Result) { + { // BLOCK + ( = ().plus(other = )) + } + { // BLOCK + val tmp0_this: Result = + tmp0_this.( = tmp0_this.().plus(other = other.())) + } +} + +operator fun Result.minus(: Int, other: Result): Result { + { // BLOCK + ( = ().plus(other = )) + } + return Result(i = .().minus(other = other.())) +} + +operator fun Result.minusAssign(: Int, other: Result) { + { // BLOCK + ( = ().plus(other = )) + } + { // BLOCK + val tmp0_this: Result = + tmp0_this.( = tmp0_this.().minus(other = other.())) + } +} + +operator fun Result.times(: Int, other: Result): Result { + { // BLOCK + ( = ().plus(other = )) + } + return Result(i = .().times(other = other.())) +} + +operator fun Result.timesAssign(: Int, other: Result) { + { // BLOCK + ( = ().plus(other = )) + } + { // BLOCK + val tmp0_this: Result = + tmp0_this.( = tmp0_this.().times(other = other.())) + } +} + +operator fun Result.div(: Int, other: Result): Result { + { // BLOCK + ( = ().plus(other = )) + } + return Result(i = .().div(other = other.())) +} + +operator fun Result.divAssign(: Int, other: Result) { + { // BLOCK + ( = ().plus(other = )) + } + { // BLOCK + val tmp0_this: Result = + tmp0_this.( = tmp0_this.().div(other = other.())) + } +} + +fun box(): String { + val result: Result = Result(i = 0) + with(receiver = 1, block = local fun Int.() { + result.plusAssign( = $this$with, other = Result(i = 1).plus( = $this$with, other = Result(i = 1))) + result.minusAssign( = $this$with, other = Result(i = 1).minus( = $this$with, other = Result(i = 0))) + result.timesAssign( = $this$with, other = Result(i = 1).times( = $this$with, other = Result(i = 2))) + result.divAssign( = $this$with, other = Result(i = 4).div( = $this$with, other = Result(i = 2))) + } +) + return when { + when { + EQEQ(arg0 = result.(), arg1 = 1) -> EQEQ(arg0 = (), arg1 = 8) + else -> false + } -> "OK" + else -> "fail" + } +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.ir.txt new file mode 100644 index 00000000000..6eb83431fe8 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.ir.txt @@ -0,0 +1,169 @@ +FILE fqName: fileName:/delegatedPropertiesOperators.kt + PROPERTY name:operationScore visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static] + EXPRESSION_BODY + CONST Int type=kotlin.Int value=0 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int + correspondingProperty: PROPERTY name:operationScore visibility:public modality:FINAL [var] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static]' type=kotlin.Int origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> (:kotlin.Int) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:operationScore visibility:public modality:FINAL [var] + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static]' type=kotlin.Unit origin=null + value: GET_VAR ': kotlin.Int declared in .' type=kotlin.Int origin=null + CLASS CLASS name:Delegate modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Delegate + CONSTRUCTOR visibility:public <> () returnType:.Delegate [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Delegate modality:FINAL visibility:public superTypes:[kotlin.Any]' + PROPERTY name:delegateValue visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:delegateValue type:kotlin.String visibility:private + EXPRESSION_BODY + CONST String type=kotlin.String value="fail" + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Delegate) returnType:kotlin.String + correspondingProperty: PROPERTY name:delegateValue visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.Delegate + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in .Delegate' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegateValue type:kotlin.String visibility:private' type=kotlin.String origin=null + receiver: GET_VAR ': .Delegate declared in .Delegate.' type=.Delegate origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Delegate, :kotlin.String) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:delegateValue visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.Delegate + VALUE_PARAMETER name: index:0 type:kotlin.String + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegateValue type:kotlin.String visibility:private' type=kotlin.Unit origin=null + receiver: GET_VAR ': .Delegate declared in .Delegate.' type=.Delegate origin=null + value: GET_VAR ': kotlin.String declared in .Delegate.' type=kotlin.String origin=null + FUN name:getValue visibility:public modality:FINAL <> ($this:.Delegate, :kotlin.Int, thisRef:kotlin.Any?, property:kotlin.reflect.KProperty<*>) returnType:kotlin.String [operator] + $this: VALUE_PARAMETER name: type:.Delegate + contextReceiverParametersCount: 1 + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:thisRef index:1 type:kotlin.Any? + VALUE_PARAMETER name:property index:2 type:kotlin.reflect.KProperty<*> + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .Delegate.getValue' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun getValue (: kotlin.Int, thisRef: kotlin.Any?, property: kotlin.reflect.KProperty<*>): kotlin.String [operator] declared in .Delegate' + CALL 'public final fun (): kotlin.String declared in .Delegate' type=kotlin.String origin=GET_PROPERTY + $this: GET_VAR ': .Delegate declared in .Delegate.getValue' type=.Delegate origin=null + FUN name:setValue visibility:public modality:FINAL <> ($this:.Delegate, :kotlin.Int, thisRef:kotlin.Any?, property:kotlin.reflect.KProperty<*>, value:kotlin.String) returnType:kotlin.Unit [operator] + $this: VALUE_PARAMETER name: type:.Delegate + contextReceiverParametersCount: 1 + VALUE_PARAMETER name: index:0 type:kotlin.Int + VALUE_PARAMETER name:thisRef index:1 type:kotlin.Any? + VALUE_PARAMETER name:property index:2 type:kotlin.reflect.KProperty<*> + VALUE_PARAMETER name:value index:3 type:kotlin.String + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .Delegate.setValue' type=kotlin.Int origin=null + CALL 'public final fun (: kotlin.String): kotlin.Unit declared in .Delegate' type=kotlin.Unit origin=EQ + $this: GET_VAR ': .Delegate declared in .Delegate.setValue' type=.Delegate origin=null + : GET_VAR 'value: kotlin.String declared in .Delegate.setValue' type=kotlin.String origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Result modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Result + FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:kotlin.Int visibility:private [final] + CONSTRUCTOR visibility:public <> (:kotlin.Int) returnType:.Result [primary] + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + SET_FIELD 'FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:kotlin.Int visibility:private [final]' type=kotlin.Unit origin=null + receiver: GET_VAR ': .Result declared in .Result' type=.Result origin=null + value: GET_VAR ': kotlin.Int declared in .Result.' type=kotlin.Int origin=null + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Result modality:FINAL visibility:public superTypes:[kotlin.Any]' + PROPERTY name:s visibility:public modality:FINAL [delegated,var] + FIELD PROPERTY_DELEGATE name:s$delegate type:.Delegate visibility:private [final] + EXPRESSION_BODY + CONSTRUCTOR_CALL 'public constructor () [primary] declared in .Delegate' type=.Delegate origin=null + FUN DELEGATED_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Result) returnType:kotlin.String + correspondingProperty: PROPERTY name:s visibility:public modality:FINAL [delegated,var] + $this: VALUE_PARAMETER name: type:.Result + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in .Result' + CALL 'public final fun getValue (: kotlin.Int, thisRef: kotlin.Any?, property: kotlin.reflect.KProperty<*>): kotlin.String [operator] declared in .Delegate' type=kotlin.String origin=null + $this: GET_FIELD 'FIELD PROPERTY_DELEGATE name:s$delegate type:.Delegate visibility:private [final]' type=.Delegate origin=null + receiver: GET_VAR ': .Result declared in .Result.' type=.Result origin=null + : GET_FIELD 'FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.' type=.Result origin=null + thisRef: GET_VAR ': .Result declared in .Result.' type=.Result origin=null + property: PROPERTY_REFERENCE 'public final s: kotlin.String [delegated,var]' field=null getter='public final fun (): kotlin.String declared in .Result' setter='public final fun (: kotlin.String): kotlin.Unit declared in .Result' type=kotlin.reflect.KMutableProperty1<.Result, kotlin.String> origin=PROPERTY_REFERENCE_FOR_DELEGATE + FUN DELEGATED_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Result, :kotlin.String) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:s visibility:public modality:FINAL [delegated,var] + $this: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (: kotlin.String): kotlin.Unit declared in .Result' + CALL 'public final fun setValue (: kotlin.Int, thisRef: kotlin.Any?, property: kotlin.reflect.KProperty<*>, value: kotlin.String): kotlin.Unit [operator] declared in .Delegate' type=kotlin.Unit origin=null + $this: GET_FIELD 'FIELD PROPERTY_DELEGATE name:s$delegate type:.Delegate visibility:private [final]' type=.Delegate origin=null + receiver: GET_VAR ': .Result declared in .Result.' type=.Result origin=null + : GET_FIELD 'FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.' type=.Result origin=null + thisRef: GET_VAR ': .Result declared in .Result.' type=.Result origin=null + property: PROPERTY_REFERENCE 'public final s: kotlin.String [delegated,var]' field=null getter='public final fun (): kotlin.String declared in .Result' setter='public final fun (: kotlin.String): kotlin.Unit declared in .Result' type=kotlin.reflect.KMutableProperty1<.Result, kotlin.String> origin=PROPERTY_REFERENCE_FOR_DELEGATE + value: GET_VAR ': kotlin.String declared in .Result.' type=kotlin.String origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + VAR name:result type:.Result [val] + CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=.Result origin=null + : kotlin.Int + : .Result + receiver: CONST Int type=kotlin.Int value=1 + block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1.Result> origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:kotlin.Int) returnType:.Result + $receiver: VALUE_PARAMETER name:$this$with type:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): .Result declared in .box' + CONSTRUCTOR_CALL 'public constructor (: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + CALL 'public final fun (: kotlin.String): kotlin.Unit declared in .Result' type=kotlin.Unit origin=EQ + $this: GET_VAR 'val result: .Result [val] declared in .box' type=.Result origin=null + : CONST String type=kotlin.String value="OK" + VAR name:returnValue type:kotlin.String [val] + CALL 'public final fun (): kotlin.String declared in .Result' type=kotlin.String origin=GET_PROPERTY + $this: GET_VAR 'val result: .Result [val] declared in .box' type=.Result origin=null + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + WHEN type=kotlin.String origin=IF + 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: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=GET_PROPERTY + arg1: CONST Int type=kotlin.Int value=2 + then: GET_VAR 'val returnValue: kotlin.String [val] declared in .box' type=kotlin.String origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST String type=kotlin.String value="fail" diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.kt b/compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.kt new file mode 100644 index 00000000000..b4c91a7f2ed --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.kt @@ -0,0 +1,36 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_STDLIB + +import kotlin.reflect.KProperty + +var operationScore = 0 + +class Delegate { + var delegateValue = "fail" + + context(Int) + operator fun getValue(thisRef: Any?, property: KProperty<*>): String { + operationScore += this@Int + return delegateValue + } + + context(Int) + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { + operationScore += this@Int + delegateValue = value + } +} + +context(Int) +class Result { + var s: String by Delegate() +} + +fun box(): String { + val result = with(1) { Result() } + result.s = "OK" + val returnValue = result.s + return if (operationScore == 2) returnValue else "fail" +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.kt.txt new file mode 100644 index 00000000000..11be2b4037c --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.kt.txt @@ -0,0 +1,65 @@ +var operationScore: Int + field = 0 + get + set + +class Delegate { + constructor() /* primary */ { + super/*Any*/() + /* () */ + + } + + var delegateValue: String + field = "fail" + get + set + + operator fun getValue(: Int, thisRef: Any?, property: KProperty<*>): String { + { // BLOCK + ( = ().plus(other = )) + } + return .() + } + + operator fun setValue(: Int, thisRef: Any?, property: KProperty<*>, value: String) { + { // BLOCK + ( = ().plus(other = )) + } + .( = value) + } + +} + +class Result { + private /* final field */ val contextReceiverField0: Int + constructor(: Int) /* primary */ { + super/*Any*/() + .#contextReceiverField0 = + /* () */ + + } + + var s: String /* by */ + field = Delegate() + get(): String { + return .#s$delegate.getValue( = .#contextReceiverField0, thisRef = , property = Result::s) + } + set(: String) { + return .#s$delegate.setValue( = .#contextReceiverField0, thisRef = , property = Result::s, value = ) + } + +} + +fun box(): String { + val result: Result = with(receiver = 1, block = local fun Int.(): Result { + return Result( = $this$with) + } +) + result.( = "OK") + val returnValue: String = result.() + return when { + EQEQ(arg0 = (), arg1 = 2) -> returnValue + else -> "fail" + } +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.ir.txt new file mode 100644 index 00000000000..a81d399a9a3 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.ir.txt @@ -0,0 +1,316 @@ +FILE fqName: fileName:/iteratorOperator.kt + CLASS CLASS name:Counter modality:FINAL visibility:public [data] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Counter + CONSTRUCTOR visibility:public <> (i:kotlin.Int) returnType:.Counter [primary] + VALUE_PARAMETER name:i index:0 type:kotlin.Int + EXPRESSION_BODY + CONST Int type=kotlin.Int value=0 + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Counter modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' + PROPERTY name:i visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private + EXPRESSION_BODY + GET_VAR 'i: kotlin.Int declared in .Counter.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Counter) returnType:kotlin.Int + correspondingProperty: PROPERTY name:i visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.Counter + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .Counter' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Counter declared in .Counter.' type=.Counter origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Counter, :kotlin.Int) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:i visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.Counter + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Unit origin=null + receiver: GET_VAR ': .Counter declared in .Counter.' type=.Counter origin=null + value: GET_VAR ': kotlin.Int declared in .Counter.' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:.Counter) returnType:kotlin.Int [operator] + $this: VALUE_PARAMETER name: type:.Counter + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.Int [operator] declared in .Counter' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Counter declared in .Counter.component1' type=.Counter origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:.Counter, i:kotlin.Int) returnType:.Counter + $this: VALUE_PARAMETER name: type:.Counter + VALUE_PARAMETER name:i index:0 type:kotlin.Int + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Counter declared in .Counter.copy' type=.Counter origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (i: kotlin.Int): .Counter declared in .Counter' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Counter' type=.Counter origin=null + i: GET_VAR 'i: kotlin.Int declared in .Counter.copy' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Counter) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Counter + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Counter' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="Counter(" + CONST String type=kotlin.String value="i=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Counter declared in .Counter.toString' type=.Counter origin=null + CONST String type=kotlin.String value=")" + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Counter) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Counter + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Counter' + CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Counter declared in .Counter.hashCode' type=.Counter origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Counter, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Counter + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': .Counter declared in .Counter.equals' type=.Counter origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in .Counter.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Counter' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=.Counter + GET_VAR 'other: kotlin.Any? declared in .Counter.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Counter' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.Counter [val] + TYPE_OP type=.Counter origin=CAST typeOperand=.Counter + GET_VAR 'other: kotlin.Any? declared in .Counter.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR ': .Counter declared in .Counter.equals' type=.Counter origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private' type=kotlin.Int origin=null + receiver: GET_VAR 'val tmp_0: .Counter [val] declared in .Counter.equals' type=.Counter origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Counter' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Counter' + CONST Boolean type=kotlin.Boolean value=true + CLASS CLASS name:CounterConfig modality:FINAL visibility:public [data] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CounterConfig + CONSTRUCTOR visibility:public <> (max:kotlin.Int) returnType:.CounterConfig [primary] + VALUE_PARAMETER name:max index:0 type:kotlin.Int + EXPRESSION_BODY + CONST Int type=kotlin.Int value=10 + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:CounterConfig modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' + PROPERTY name:max visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:max type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + GET_VAR 'max: kotlin.Int declared in .CounterConfig.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.CounterConfig) returnType:kotlin.Int + correspondingProperty: PROPERTY name:max visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.CounterConfig + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .CounterConfig' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:max type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .CounterConfig declared in .CounterConfig.' type=.CounterConfig origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:.CounterConfig) returnType:kotlin.Int [operator] + $this: VALUE_PARAMETER name: type:.CounterConfig + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.Int [operator] declared in .CounterConfig' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:max type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .CounterConfig declared in .CounterConfig.component1' type=.CounterConfig origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:.CounterConfig, max:kotlin.Int) returnType:.CounterConfig + $this: VALUE_PARAMETER name: type:.CounterConfig + VALUE_PARAMETER name:max index:0 type:kotlin.Int + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:max type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .CounterConfig declared in .CounterConfig.copy' type=.CounterConfig origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (max: kotlin.Int): .CounterConfig declared in .CounterConfig' + CONSTRUCTOR_CALL 'public constructor (max: kotlin.Int) [primary] declared in .CounterConfig' type=.CounterConfig origin=null + max: GET_VAR 'max: kotlin.Int declared in .CounterConfig.copy' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:.CounterConfig) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.CounterConfig + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .CounterConfig' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="CounterConfig(" + CONST String type=kotlin.String value="max=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:max type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .CounterConfig declared in .CounterConfig.toString' type=.CounterConfig origin=null + CONST String type=kotlin.String value=")" + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.CounterConfig) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.CounterConfig + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .CounterConfig' + CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:max type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .CounterConfig declared in .CounterConfig.hashCode' type=.CounterConfig origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.CounterConfig, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.CounterConfig + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': .CounterConfig declared in .CounterConfig.equals' type=.CounterConfig origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in .CounterConfig.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .CounterConfig' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=.CounterConfig + GET_VAR 'other: kotlin.Any? declared in .CounterConfig.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .CounterConfig' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:.CounterConfig [val] + TYPE_OP type=.CounterConfig origin=CAST typeOperand=.CounterConfig + GET_VAR 'other: kotlin.Any? declared in .CounterConfig.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:max type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .CounterConfig declared in .CounterConfig.equals' type=.CounterConfig origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:max type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR 'val tmp_1: .CounterConfig [val] declared in .CounterConfig.equals' type=.CounterConfig origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .CounterConfig' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .CounterConfig' + CONST Boolean type=kotlin.Boolean value=true + CLASS CLASS name:CounterIterator modality:FINAL visibility:public superTypes:[kotlin.collections.Iterator] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CounterIterator + FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:.CounterConfig visibility:private [final] + CONSTRUCTOR visibility:public <> (:.CounterConfig, counter:.Counter) returnType:.CounterIterator [primary] + VALUE_PARAMETER name: index:0 type:.CounterConfig + VALUE_PARAMETER name:counter index:1 type:.Counter + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + SET_FIELD 'FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:.CounterConfig visibility:private [final]' type=kotlin.Unit origin=null + receiver: GET_VAR ': .CounterIterator declared in .CounterIterator' type=.CounterIterator origin=null + value: GET_VAR ': .CounterConfig declared in .CounterIterator.' type=.CounterConfig origin=null + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:CounterIterator modality:FINAL visibility:public superTypes:[kotlin.collections.Iterator]' + PROPERTY name:counter visibility:private modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:counter type:.Counter visibility:private [final] + EXPRESSION_BODY + GET_VAR 'counter: .Counter declared in .CounterIterator.' type=.Counter origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.CounterIterator) returnType:.Counter + correspondingProperty: PROPERTY name:counter visibility:private modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.CounterIterator + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun (): .Counter declared in .CounterIterator' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:counter type:.Counter visibility:private [final]' type=.Counter origin=null + receiver: GET_VAR ': .CounterIterator declared in .CounterIterator.' type=.CounterIterator origin=null + FUN name:hasNext visibility:public modality:OPEN <> ($this:.CounterIterator) returnType:kotlin.Boolean [operator] + overridden: + public abstract fun hasNext (): kotlin.Boolean [operator] declared in kotlin.collections.Iterator + $this: VALUE_PARAMETER name: type:.CounterIterator + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hasNext (): kotlin.Boolean [operator] declared in .CounterIterator' + CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT + arg0: CALL 'public final fun (): kotlin.Int declared in .Counter' type=kotlin.Int origin=GET_PROPERTY + $this: CALL 'private final fun (): .Counter declared in .CounterIterator' type=.Counter origin=GET_PROPERTY + $this: GET_VAR ': .CounterIterator declared in .CounterIterator.hasNext' type=.CounterIterator origin=null + arg1: CALL 'public final fun (): kotlin.Int declared in .CounterConfig' type=kotlin.Int origin=GET_PROPERTY + $this: GET_FIELD 'FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:.CounterConfig visibility:private [final]' type=.CounterConfig origin=null + receiver: GET_VAR ': .CounterIterator declared in .CounterIterator.hasNext' type=.CounterIterator origin=null + FUN name:next visibility:public modality:OPEN <> ($this:.CounterIterator) returnType:kotlin.Int [operator] + overridden: + public abstract fun next (): T of kotlin.collections.Iterator [operator] declared in kotlin.collections.Iterator + $this: VALUE_PARAMETER name: type:.CounterIterator + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun next (): kotlin.Int [operator] declared in .CounterIterator' + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:.Counter [val] + CALL 'private final fun (): .Counter declared in .CounterIterator' type=.Counter origin=GET_PROPERTY + $this: GET_VAR ': .CounterIterator declared in .CounterIterator.next' type=.CounterIterator origin=null + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.Int [val] + CALL 'public final fun (): kotlin.Int declared in .Counter' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'val tmp_2: .Counter [val] declared in .CounterIterator.next' type=.Counter origin=null + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in .Counter' type=kotlin.Unit origin=POSTFIX_INCR + $this: GET_VAR 'val tmp_2: .Counter [val] declared in .CounterIterator.next' type=.Counter origin=null + : CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'val tmp_3: kotlin.Int [val] declared in .CounterIterator.next' type=kotlin.Int origin=null + GET_VAR 'val tmp_3: kotlin.Int [val] declared in .CounterIterator.next' type=kotlin.Int origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in kotlin.collections.Iterator + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.collections.Iterator + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in kotlin.collections.Iterator + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN name:iterator visibility:public modality:FINAL <> ($receiver:.Counter, :.CounterConfig) returnType:.CounterIterator [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Counter + VALUE_PARAMETER name: index:0 type:.CounterConfig + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun iterator (: .CounterConfig): .CounterIterator [operator] declared in ' + CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=.CounterIterator origin=null + : .CounterConfig + : .CounterIterator + receiver: GET_VAR ': .CounterConfig declared in .iterator' type=.CounterConfig origin=null + block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1<.CounterConfig, .CounterIterator> origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:.CounterConfig) returnType:.CounterIterator + $receiver: VALUE_PARAMETER name:$this$with type:.CounterConfig + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): .CounterIterator declared in .iterator' + CONSTRUCTOR_CALL 'public constructor (: .CounterConfig, counter: .Counter) [primary] declared in .CounterIterator' type=.CounterIterator origin=null + : GET_VAR '$this$with: .CounterConfig declared in .iterator.' type=.CounterConfig origin=null + counter: GET_VAR ': .Counter declared in .iterator' type=.Counter origin=null + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + VAR name:result type:kotlin.Int [var] + CONST Int type=kotlin.Int value=0 + CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.Unit origin=null + : .CounterConfig + : kotlin.Unit + receiver: CONSTRUCTOR_CALL 'public constructor (max: kotlin.Int) [primary] declared in .CounterConfig' type=.CounterConfig origin=null + block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1<.CounterConfig, kotlin.Unit> origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:.CounterConfig) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER name:$this$with type:.CounterConfig + BLOCK_BODY + BLOCK type=kotlin.Unit origin=FOR_LOOP + VAR FOR_LOOP_ITERATOR name:tmp_4 type:.CounterIterator [val] + CALL 'public final fun iterator (: .CounterConfig): .CounterIterator [operator] declared in ' type=.CounterIterator origin=FOR_LOOP_ITERATOR + $receiver: CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Counter' type=.Counter origin=null + : GET_VAR '$this$with: .CounterConfig declared in .box.' type=.CounterConfig origin=null + WHILE label=null origin=FOR_LOOP_INNER_WHILE + condition: CALL 'public open fun hasNext (): kotlin.Boolean [operator] declared in .CounterIterator' type=kotlin.Boolean origin=FOR_LOOP_HAS_NEXT + $this: GET_VAR 'val tmp_4: .CounterIterator [val] declared in .box.' type=.CounterIterator origin=null + body: BLOCK type=kotlin.Unit origin=FOR_LOOP_INNER_WHILE + VAR FOR_LOOP_VARIABLE name:i type:kotlin.Int [val] + CALL 'public open fun next (): kotlin.Int [operator] declared in .CounterIterator' type=kotlin.Int origin=FOR_LOOP_NEXT + $this: GET_VAR 'val tmp_4: .CounterIterator [val] declared in .box.' type=.CounterIterator origin=null + BLOCK type=kotlin.Unit origin=null + SET_VAR 'var result: kotlin.Int [var] declared in .box' type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: GET_VAR 'var result: kotlin.Int [var] declared in .box' type=kotlin.Int origin=PLUSEQ + other: GET_VAR 'val i: kotlin.Int [val] declared in .box.' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + WHEN type=kotlin.String origin=IF + 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 'var result: kotlin.Int [var] declared in .box' type=kotlin.Int origin=null + arg1: CONST Int type=kotlin.Int value=45 + then: CONST String type=kotlin.String value="OK" + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST String type=kotlin.String value="fail" diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.kt b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.kt new file mode 100644 index 00000000000..49390ed3dff --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.kt @@ -0,0 +1,28 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_STDLIB + +data class Counter(var i: Int = 0) + +data class CounterConfig(val max: Int = 10) + +context(CounterConfig) +class CounterIterator(private val counter: Counter) : Iterator { + override fun hasNext() = counter.i < max + override fun next() = counter.i++ +} + +context(CounterConfig) +operator fun Counter.iterator() = with(this@CounterConfig) { CounterIterator(this@Counter) } + + +fun box(): String { + var result = 0 + with(CounterConfig()) { + for (i in Counter()) { + result += i + } + } + return if (result == 45) "OK" else "fail" +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.kt.txt new file mode 100644 index 00000000000..2100410127f --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.kt.txt @@ -0,0 +1,143 @@ +data class Counter { + constructor(i: Int = 0) /* primary */ { + super/*Any*/() + /* () */ + + } + + var i: Int + field = i + get + set + + operator fun component1(): Int { + return .#i + } + + fun copy(i: Int = .#i): Counter { + return Counter(i = i) + } + + override fun toString(): String { + return "Counter(" + "i=" + .#i + ")" + } + + override fun hashCode(): Int { + return .#i.hashCode() + } + + override operator fun equals(other: Any?): Boolean { + when { + EQEQEQ(arg0 = , arg1 = other) -> return true + } + when { + other !is Counter -> return false + } + val tmp0_other_with_cast: Counter = other as Counter + when { + EQEQ(arg0 = .#i, arg1 = tmp0_other_with_cast.#i).not() -> return false + } + return true + } + +} + +data class CounterConfig { + constructor(max: Int = 10) /* primary */ { + super/*Any*/() + /* () */ + + } + + val max: Int + field = max + get + + operator fun component1(): Int { + return .#max + } + + fun copy(max: Int = .#max): CounterConfig { + return CounterConfig(max = max) + } + + override fun toString(): String { + return "CounterConfig(" + "max=" + .#max + ")" + } + + override fun hashCode(): Int { + return .#max.hashCode() + } + + override operator fun equals(other: Any?): Boolean { + when { + EQEQEQ(arg0 = , arg1 = other) -> return true + } + when { + other !is CounterConfig -> return false + } + val tmp0_other_with_cast: CounterConfig = other as CounterConfig + when { + EQEQ(arg0 = .#max, arg1 = tmp0_other_with_cast.#max).not() -> return false + } + return true + } + +} + +class CounterIterator : Iterator { + private /* final field */ val contextReceiverField0: CounterConfig + constructor(: CounterConfig, counter: Counter) /* primary */ { + super/*Any*/() + .#contextReceiverField0 = + /* () */ + + } + + private val counter: Counter + field = counter + private get + + override operator fun hasNext(): Boolean { + return less(arg0 = .().(), arg1 = .#contextReceiverField0.()) + } + + override operator fun next(): Int { + return { // BLOCK + val tmp0_this: Counter = .() + { // BLOCK + val tmp1: Int = tmp0_this.() + tmp0_this.( = tmp1.inc()) + tmp1 + } + } + } + +} + +operator fun Counter.iterator(: CounterConfig): CounterIterator { + return with(receiver = , block = local fun CounterConfig.(): CounterIterator { + return CounterIterator( = $this$with, counter = ) + } +) +} + +fun box(): String { + var result: Int = 0 + with(receiver = CounterConfig(), block = local fun CounterConfig.() { + { // BLOCK + val tmp0_iterator: CounterIterator = Counter().iterator( = $this$with) + while (tmp0_iterator.hasNext()) { // BLOCK + val i: Int = tmp0_iterator.next() + { // BLOCK + result = result.plus(other = i) + } + } + } + } +) + return when { + EQEQ(arg0 = result, arg1 = 45) -> "OK" + else -> "fail" + } +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.ir.txt new file mode 100644 index 00000000000..c6147e9b6d4 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.ir.txt @@ -0,0 +1,245 @@ +FILE fqName: fileName:/unaryOperators.kt + CLASS CLASS name:Result modality:FINAL visibility:public [data] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Result + CONSTRUCTOR visibility:public <> (i:kotlin.Int) returnType:.Result [primary] + VALUE_PARAMETER name:i index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Result modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' + PROPERTY name:i visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + GET_VAR 'i: kotlin.Int declared in .Result.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Result) returnType:kotlin.Int + correspondingProperty: PROPERTY name:i visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Result + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .Result' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.' type=.Result origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:.Result) returnType:kotlin.Int [operator] + $this: VALUE_PARAMETER name: type:.Result + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.Int [operator] declared in .Result' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.component1' type=.Result origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:.Result, i:kotlin.Int) returnType:.Result + $this: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name:i index:0 type:kotlin.Int + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.copy' type=.Result origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (i: kotlin.Int): .Result declared in .Result' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: GET_VAR 'i: kotlin.Int declared in .Result.copy' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Result) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Result + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Result' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="Result(" + CONST String type=kotlin.String value="i=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.toString' type=.Result origin=null + CONST String type=kotlin.String value=")" + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Result) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Result + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Result' + CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.hashCode' type=.Result origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Result, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': .Result declared in .Result.equals' type=.Result origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in .Result.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Result' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=.Result + GET_VAR 'other: kotlin.Any? declared in .Result.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Result' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.Result [val] + TYPE_OP type=.Result origin=CAST typeOperand=.Result + GET_VAR 'other: kotlin.Any? declared in .Result.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Result declared in .Result.equals' type=.Result origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:i type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR 'val tmp_0: .Result [val] declared in .Result.equals' type=.Result origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Result' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Result' + CONST Boolean type=kotlin.Boolean value=true + PROPERTY name:operationScore visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static] + EXPRESSION_BODY + CONST Int type=kotlin.Int value=0 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int + correspondingProperty: PROPERTY name:operationScore visibility:public modality:FINAL [var] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static]' type=kotlin.Int origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> (:kotlin.Int) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:operationScore visibility:public modality:FINAL [var] + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:operationScore type:kotlin.Int visibility:private [static]' type=kotlin.Unit origin=null + value: GET_VAR ': kotlin.Int declared in .' type=kotlin.Int origin=null + FUN name:unaryMinus visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int) returnType:.Result [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .unaryMinus' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun unaryMinus (: kotlin.Int): .Result [operator] declared in ' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=UMINUS + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .unaryMinus' type=.Result origin=null + FUN name:unaryPlus visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int) returnType:.Result [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .unaryPlus' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun unaryPlus (: kotlin.Int): .Result [operator] declared in ' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: WHEN type=kotlin.Int origin=IF + BRANCH + if: CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT + arg0: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .unaryPlus' type=.Result origin=null + arg1: CONST Int type=kotlin.Int value=0 + then: CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=UMINUS + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .unaryPlus' type=.Result origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .unaryPlus' type=.Result origin=null + FUN name:inc visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int) returnType:.Result [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .inc' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun inc (: kotlin.Int): .Result [operator] declared in ' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .inc' type=.Result origin=null + other: CONST Int type=kotlin.Int value=1 + FUN name:dec visibility:public modality:FINAL <> ($receiver:.Result, :kotlin.Int) returnType:.Result [operator] + contextReceiverParametersCount: 1 + $receiver: VALUE_PARAMETER name: type:.Result + VALUE_PARAMETER name: index:0 type:kotlin.Int + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + CALL 'public final fun (: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=PLUSEQ + : CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=PLUSEQ + other: GET_VAR ': kotlin.Int declared in .dec' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='public final fun dec (: kotlin.Int): .Result [operator] declared in ' + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CALL 'public final fun minus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=MINUS + $this: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR ': .Result declared in .dec' type=.Result origin=null + other: CONST Int type=kotlin.Int value=1 + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + VAR name:result type:.Result [var] + CONSTRUCTOR_CALL 'public constructor (i: kotlin.Int) [primary] declared in .Result' type=.Result origin=null + i: CONST Int type=kotlin.Int value=0 + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=.Result origin=null + : kotlin.Int + : .Result + receiver: CONST Int type=kotlin.Int value=1 + block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1.Result> origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:kotlin.Int) returnType:.Result + $receiver: VALUE_PARAMETER name:$this$with type:kotlin.Int + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=.Result origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:.Result [val] + GET_VAR 'var result: .Result [var] declared in .box' type=.Result origin=POSTFIX_INCR + SET_VAR 'var result: .Result [var] declared in .box' type=kotlin.Unit origin=POSTFIX_INCR + CALL 'public final fun inc (: kotlin.Int): .Result [operator] declared in ' type=.Result origin=POSTFIX_INCR + $receiver: GET_VAR 'val tmp_1: .Result [val] declared in .box.' type=.Result origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + GET_VAR 'val tmp_1: .Result [val] declared in .box.' type=.Result origin=null + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=.Result origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:.Result [val] + GET_VAR 'var result: .Result [var] declared in .box' type=.Result origin=POSTFIX_INCR + SET_VAR 'var result: .Result [var] declared in .box' type=kotlin.Unit origin=POSTFIX_INCR + CALL 'public final fun inc (: kotlin.Int): .Result [operator] declared in ' type=.Result origin=POSTFIX_INCR + $receiver: GET_VAR 'val tmp_2: .Result [val] declared in .box.' type=.Result origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + GET_VAR 'val tmp_2: .Result [val] declared in .box.' type=.Result origin=null + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public final fun unaryMinus (: kotlin.Int): .Result [operator] declared in ' type=.Result origin=UMINUS + $receiver: GET_VAR 'var result: .Result [var] declared in .box' type=.Result origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public final fun unaryPlus (: kotlin.Int): .Result [operator] declared in ' type=.Result origin=UPLUS + $receiver: GET_VAR 'var result: .Result [var] declared in .box' type=.Result origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + RETURN type=kotlin.Nothing from='local final fun (): .Result declared in .box' + BLOCK type=.Result origin=POSTFIX_DECR + VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:.Result [val] + GET_VAR 'var result: .Result [var] declared in .box' type=.Result origin=POSTFIX_DECR + SET_VAR 'var result: .Result [var] declared in .box' type=kotlin.Unit origin=POSTFIX_DECR + CALL 'public final fun dec (: kotlin.Int): .Result [operator] declared in ' type=.Result origin=POSTFIX_DECR + $receiver: GET_VAR 'val tmp_3: .Result [val] declared in .box.' type=.Result origin=null + : GET_VAR '$this$with: kotlin.Int declared in .box.' type=kotlin.Int origin=null + GET_VAR 'val tmp_3: .Result [val] declared in .box.' type=.Result origin=null + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + WHEN type=kotlin.String origin=IF + BRANCH + if: WHEN type=kotlin.Boolean origin=ANDAND + 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: CALL 'public final fun (): kotlin.Int declared in .Result' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'var result: .Result [var] declared in .box' type=.Result origin=null + arg1: CONST Int type=kotlin.Int value=1 + then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: CALL 'public final fun (): kotlin.Int declared in ' type=kotlin.Int origin=GET_PROPERTY + arg1: CONST Int type=kotlin.Int value=5 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Boolean type=kotlin.Boolean value=false + then: CONST String type=kotlin.String value="OK" + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST String type=kotlin.String value="fail" diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.kt b/compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.kt new file mode 100644 index 00000000000..3615e5a32dd --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.kt @@ -0,0 +1,45 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +data class Result(val i: Int) + +var operationScore = 0 + +context(Int) +operator fun Result.unaryMinus(): Result { + operationScore += this@Int + return Result(-i) +} + +context(Int) +operator fun Result.unaryPlus(): Result { + operationScore += this@Int + return Result(if (i < 0) (-i) else i) +} + +context(Int) +operator fun Result.inc(): Result { + operationScore += this@Int + return Result(i + 1) +} + +context(Int) +operator fun Result.dec(): Result { + operationScore += this@Int + return Result(i - 1) +} + +fun box(): String { + var result = Result(0) + with(1) { + result++ + result++ + (-result) + +result + result-- + } + return if (result.i == 1 && operationScore == 5) "OK" else "fail" +} + + diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.kt.txt new file mode 100644 index 00000000000..2ce505a1ee6 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.kt.txt @@ -0,0 +1,109 @@ +data class Result { + constructor(i: Int) /* primary */ { + super/*Any*/() + /* () */ + + } + + val i: Int + field = i + get + + operator fun component1(): Int { + return .#i + } + + fun copy(i: Int = .#i): Result { + return Result(i = i) + } + + override fun toString(): String { + return "Result(" + "i=" + .#i + ")" + } + + override fun hashCode(): Int { + return .#i.hashCode() + } + + override operator fun equals(other: Any?): Boolean { + when { + EQEQEQ(arg0 = , arg1 = other) -> return true + } + when { + other !is Result -> return false + } + val tmp0_other_with_cast: Result = other as Result + when { + EQEQ(arg0 = .#i, arg1 = tmp0_other_with_cast.#i).not() -> return false + } + return true + } + +} + +var operationScore: Int + field = 0 + get + set + +operator fun Result.unaryMinus(: Int): Result { + { // BLOCK + ( = ().plus(other = )) + } + return Result(i = .().unaryMinus()) +} + +operator fun Result.unaryPlus(: Int): Result { + { // BLOCK + ( = ().plus(other = )) + } + return Result(i = when { + less(arg0 = .(), arg1 = 0) -> .().unaryMinus() + else -> .() + }) +} + +operator fun Result.inc(: Int): Result { + { // BLOCK + ( = ().plus(other = )) + } + return Result(i = .().plus(other = 1)) +} + +operator fun Result.dec(: Int): Result { + { // BLOCK + ( = ().plus(other = )) + } + return Result(i = .().minus(other = 1)) +} + +fun box(): String { + var result: Result = Result(i = 0) + with(receiver = 1, block = local fun Int.(): Result { + { // BLOCK + val tmp0: Result = result + result = tmp0.inc( = $this$with) + tmp0 + } /*~> Unit */ + { // BLOCK + val tmp1: Result = result + result = tmp1.inc( = $this$with) + tmp1 + } /*~> Unit */ + result.unaryMinus( = $this$with) /*~> Unit */ + result.unaryPlus( = $this$with) /*~> Unit */ + return { // BLOCK + val tmp2: Result = result + result = tmp2.dec( = $this$with) + tmp2 + } + } +) /*~> Unit */ + return when { + when { + EQEQ(arg0 = result.(), arg1 = 1) -> EQEQ(arg0 = (), arg1 = 5) + else -> false + } -> "OK" + else -> "fail" + } +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index f8bf505ee6e..9bd16238325 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -16175,18 +16175,48 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("arrayAccessCompositeOperators.kt") + public void testArrayAccessCompositeOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessCompositeOperators.kt"); + } + + @Test + @TestMetadata("arrayAccessOperators.kt") + public void testArrayAccessOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessOperators.kt"); + } + + @Test + @TestMetadata("compoundAssignmentOperators.kt") + public void testCompoundAssignmentOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/compoundAssignmentOperators.kt"); + } + @Test @TestMetadata("contextAndExtensionSameName.kt") public void testContextAndExtensionSameName() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/contextAndExtensionSameName.kt"); } + @Test + @TestMetadata("delegatedPropertiesOperators.kt") + public void testDelegatedPropertiesOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/delegatedPropertiesOperators.kt"); + } + @Test @TestMetadata("inferGenericPropertyType.kt") public void testInferGenericPropertyType() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/inferGenericPropertyType.kt"); } + @Test + @TestMetadata("iteratorOperator.kt") + public void testIteratorOperator() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/iteratorOperator.kt"); + } + @Test @TestMetadata("localDeclaration.kt") public void testLocalDeclaration() throws Exception { @@ -16229,6 +16259,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/this.kt"); } + @Test + @TestMetadata("unaryOperators.kt") + public void testUnaryOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/unaryOperators.kt"); + } + @Test @TestMetadata("useFromAnotherModule.kt") public void testUseFromAnotherModule() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java index ab769675e4d..92e4dca6c1f 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java @@ -751,18 +751,42 @@ public class IrTextTestGenerated extends AbstractIrTextTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irText/declarations/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("arrayAccessCompositeOperators.kt") + public void testArrayAccessCompositeOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessCompositeOperators.kt"); + } + + @Test + @TestMetadata("arrayAccessOperators.kt") + public void testArrayAccessOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/arrayAccessOperators.kt"); + } + @Test @TestMetadata("class.kt") public void testClass() throws Exception { runTest("compiler/testData/ir/irText/declarations/contextReceivers/class.kt"); } + @Test + @TestMetadata("compoundAssignmentOperators.kt") + public void testCompoundAssignmentOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt"); + } + @Test @TestMetadata("contextualPrimaryConstructorWithParams.kt") public void testContextualPrimaryConstructorWithParams() throws Exception { runTest("compiler/testData/ir/irText/declarations/contextReceivers/contextualPrimaryConstructorWithParams.kt"); } + @Test + @TestMetadata("delegatedPropertiesOperators.kt") + public void testDelegatedPropertiesOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/delegatedPropertiesOperators.kt"); + } + @Test @TestMetadata("function.kt") public void testFunction() throws Exception { @@ -781,6 +805,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest { runTest("compiler/testData/ir/irText/declarations/contextReceivers/genericOuterClass.kt"); } + @Test + @TestMetadata("iteratorOperator.kt") + public void testIteratorOperator() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.kt"); + } + @Test @TestMetadata("lazy.kt") public void testLazy() throws Exception { @@ -823,6 +853,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest { runTest("compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.kt"); } + @Test + @TestMetadata("unaryOperators.kt") + public void testUnaryOperators() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/unaryOperators.kt"); + } + @Nested @TestMetadata("compiler/testData/ir/irText/declarations/contextReceivers/fromKEEP") @TestDataPath("$PROJECT_ROOT") diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java index 1b43228e5ac..b834b443590 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java @@ -16362,18 +16362,48 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @Test + @TestMetadata("arrayAccessCompositeOperators.kt") + public void testArrayAccessCompositeOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessCompositeOperators.kt"); + } + + @Test + @TestMetadata("arrayAccessOperators.kt") + public void testArrayAccessOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/arrayAccessOperators.kt"); + } + + @Test + @TestMetadata("compoundAssignmentOperators.kt") + public void testCompoundAssignmentOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/compoundAssignmentOperators.kt"); + } + @Test @TestMetadata("contextAndExtensionSameName.kt") public void testContextAndExtensionSameName() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/contextAndExtensionSameName.kt"); } + @Test + @TestMetadata("delegatedPropertiesOperators.kt") + public void testDelegatedPropertiesOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/delegatedPropertiesOperators.kt"); + } + @Test @TestMetadata("inferGenericPropertyType.kt") public void testInferGenericPropertyType() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/inferGenericPropertyType.kt"); } + @Test + @TestMetadata("iteratorOperator.kt") + public void testIteratorOperator() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/iteratorOperator.kt"); + } + @Test @TestMetadata("localDeclaration.kt") public void testLocalDeclaration() throws Exception { @@ -16416,6 +16446,12 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/this.kt"); } + @Test + @TestMetadata("unaryOperators.kt") + public void testUnaryOperators() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/unaryOperators.kt"); + } + @Test @TestMetadata("useFromAnotherModule.kt") public void testUseFromAnotherModule() throws Exception {