diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/compoundAssignWithArrayAccessConvention.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/compoundAssignWithArrayAccessConvention.txt index b9f3aa7569c..4bf2988de44 100644 --- a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/compoundAssignWithArrayAccessConvention.txt +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/compoundAssignWithArrayAccessConvention.txt @@ -1,6 +1,6 @@ KT element: KtBinaryExpression FIR element: FirFunctionCallImpl -FIR source kind: DesugaredCompoundAssignment +FIR source kind: KtRealSourceElementKind FIR element rendered: -R|/<>|.R|SubstitutionOverride|(R|/<>|, R|/<>|.R|SubstitutionOverride|(R|/<>|).R|kotlin/Int.plus|(Int(1))) \ No newline at end of file +R|/<>|.R|SubstitutionOverride|(R|/<>|, R|/<>|.R|SubstitutionOverride|(R|/<>|).R|kotlin/Int.plus|(Int(1))) diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java index 127aad04b29..05364a67297 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java @@ -863,6 +863,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/callResolution"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("arraySetWithPlusAssign.kt") + public void testArraySetWithPlusAssign() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.kt"); + } + @Test @TestMetadata("companionInvoke.kt") public void testCompanionInvoke() throws Exception { @@ -893,6 +899,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt"); } + @Test + @TestMetadata("exponentialArraySetWithPlusAssign.kt") + public void testExponentialArraySetWithPlusAssign() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.kt"); + } + @Test @TestMetadata("extensionInvokeAfterSafeCall.kt") public void testExtensionInvokeAfterSafeCall() throws Exception { diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index ed1ee85cbba..49df06132e5 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -745,6 +745,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/callResolution"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @TestMetadata("arraySetWithPlusAssign.kt") + public void testArraySetWithPlusAssign() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.kt"); + } + @TestMetadata("companionInvoke.kt") public void testCompanionInvoke() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/companionInvoke.kt"); @@ -770,6 +775,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt"); } + @TestMetadata("exponentialArraySetWithPlusAssign.kt") + public void testExponentialArraySetWithPlusAssign() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.kt"); + } + @TestMetadata("extensionInvokeAfterSafeCall.kt") public void testExtensionInvokeAfterSafeCall() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/extensionInvokeAfterSafeCall.kt"); diff --git a/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.fir.txt index 0d836700b8a..a77bde54efe 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.fir.txt @@ -56,8 +56,8 @@ FILE: arraySetWithOperation.kt } public final fun test_3(a: R|A|): R|kotlin/Unit| { - ArraySet:[R|/a|.R|SubstitutionOverride|(Int(0)) += R|/D.D|()] + R|/a|.R|SubstitutionOverride|(Int(0)).#(R|/D.D|()) } public final fun test_4(b: R|B|): R|kotlin/Unit| { - ArraySet:[R|/b|.#(Int(0)) += R|/B.B|()] + R|/b|.#(Int(0)).#(R|/B.B|()) } diff --git a/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt b/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt index cfbe55ad6cf..bef6b20890a 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt +++ b/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt @@ -28,9 +28,9 @@ fun test_2(a: A) { } fun test_3(a: A) { - a[0] += D() // ambiguity + a[0] += D() // ambiguity } fun test_4(b: B) { - b[0] += B() // unresolved + b[0] += B() // unresolved } diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.fir.txt b/compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.fir.txt new file mode 100644 index 00000000000..924d225c2e7 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.fir.txt @@ -0,0 +1,201 @@ +FILE: arraySetWithPlusAssign.kt + public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + public final operator fun get(i: R|kotlin/Int|): R|A| { + ^get this@R|/A| + } + + public final operator fun plusAssign(v: R|() -> kotlin/Unit|): R|kotlin/Unit| { + } + + } + public final fun test_1(x: R|A|): R|kotlin/Unit| { + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + Q|kotlin/Unit| + } + ) + } + ) + } + public final class B : R|kotlin/Any| { + public constructor(): R|B| { + super() + } + + public final operator fun get(i: R|kotlin/Int|): R|B| { + ^get this@R|/B| + } + + public final operator fun plusAssign(a: R|() -> kotlin/Unit|): R|kotlin/Unit| { + } + + public final operator fun plus(x: R|kotlin/String|): R|kotlin/Unit| { + } + + } + public final fun test_2(x: R|B|): R|kotlin/Unit| { + R|/x|.R|/B.get|(Int(1)).R|/B.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/B.get|(Int(1)).R|/B.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + Q|kotlin/Unit| + } + ) + } + ) + } + public final class C : R|kotlin/Any| { + public constructor(): R|C| { + super() + } + + public final operator fun get(i: R|kotlin/Int|): R|C| { + ^get this@R|/C| + } + + public final operator fun set(i: R|kotlin/Int|, v: R|kotlin/String|): R|kotlin/Unit| { + } + + public final operator fun plusAssign(a: R|() -> kotlin/Unit|): R|kotlin/Unit| { + } + + public final operator fun plus(v: R|() -> kotlin/Unit|): R|kotlin/Unit| { + } + + } + public final fun test_3(x: R|C|): R|kotlin/Unit| { + R|/x|.R|/C.get|(Int(1)).R|/C.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/C.get|(Int(1)).R|/C.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + Q|kotlin/Unit| + } + ) + } + ) + } + public final class D : R|kotlin/Any| { + public constructor(): R|D| { + super() + } + + public final operator fun set(i: R|kotlin/Int|, x: R|D|): R|kotlin/Unit| { + } + + public final operator fun get(i: R|kotlin/Int|): R|D| { + ^get this@R|/D| + } + + public final operator fun plusAssign(x: R|() -> kotlin/Unit|): R|kotlin/Unit| { + } + + public final operator fun plus(v: R|() -> kotlin/Unit|): R|D| { + ^plus this@R|/D| + } + + } + public final fun test_4(x: R|D|): R|kotlin/Unit| { + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + Q|kotlin/Unit| + } + ) + } + ) + } + public final class E : R|kotlin/Any| { + public constructor(): R|E| { + super() + } + + } + public final fun test_5(x: R|E|): R|kotlin/Unit| { + R|/x|.#(Int(1)).#(fun (): { + R|/someCallInsideLambda|() + ^ R|/x|.#(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + Q|kotlin/Unit| + } + ) + } + ) + } + public final class F : R|kotlin/Any| { + public constructor(): R|F| { + super() + } + + public final operator fun set(i: R|kotlin/Int|, x: R|F|): R|kotlin/Unit| { + } + + public final operator fun get(i: R|kotlin/Int|): R|F| { + ^get this@R|/F| + } + + public final operator fun plusAssign(x: R|() -> kotlin/String|): R|kotlin/Unit| { + } + + public final operator fun plus(v: R|() -> kotlin/Int|): R|F| { + ^plus this@R|/F| + } + + } + public final fun test_6(x: R|F|): R|kotlin/Unit| { + R|/x|.R|/F.get|(Int(1)).#(fun (): R|kotlin/String| { + R|/someCallInsideLambda|() + ^ String(please choose String) + } + ) + } + public final class G : R|kotlin/Any| { + public constructor(): R|G| { + super() + } + + public final operator fun get(i: R|kotlin/Int|, j: R|kotlin/Int|, k: R|kotlin/Int|): R|G| { + ^get this@R|/G| + } + + public final operator fun set(i: R|kotlin/Int|, j: R|kotlin/Int|, k: R|kotlin/Int|, x: R|G|): R|kotlin/Unit| { + } + + public final operator fun plus(v: R|() -> kotlin/Unit|): R|G| { + ^plus this@R|/G| + } + + } + public final fun test_7(x: R|G|): R|kotlin/Unit| { + { + lval <>: R|G| = R|/x| + lval <>: R|kotlin/Int| = Int(1) + lval <>: R|kotlin/Int| = Int(2) + lval <>: R|kotlin/Int| = Int(3) + R|/<>|.R|/G.set|(R|/<>|, R|/<>|, R|/<>|, R|/<>|.R|/G.get|(R|/<>|, R|/<>|, R|/<>|).R|/G.plus|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + { + lval <>: R|G| = R|/x| + lval <>: R|kotlin/Int| = Int(1) + lval <>: R|kotlin/Int| = Int(2) + lval <>: R|kotlin/Int| = Int(3) + R|/<>|.R|/G.set|(R|/<>|, R|/<>|, R|/<>|, R|/<>|.R|/G.get|(R|/<>|, R|/<>|, R|/<>|).R|/G.plus|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + Q|kotlin/Unit| + } + )) + } + + } + )) + } + + } + public final fun someCallInsideLambda(): R|kotlin/Unit| { + } diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.kt b/compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.kt new file mode 100644 index 00000000000..0633eb6c504 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.kt @@ -0,0 +1,125 @@ +// ISSUE: KT-50861 + +/* + * a[b] += c desugars to: + * + * 1. a.get(b).plusAssign(c) + * 2. a.set(b, a.get(b).plus(c)) + */ + +// only plusAssign, no set +class A { + operator fun get(i: Int): A = this + operator fun plusAssign(v: () -> Unit) {} +} + +fun test_1(x: A) { + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + Unit + } + } +} + +// only plusAssign, plus doesn't fit +class B { + operator fun get(i: Int): B = this + operator fun plusAssign(a: () -> Unit) {} + operator fun plus(x: String) {} +} + +fun test_2(x: B) { + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + Unit + } + } +} + +// only plusAssign, set doesn't fit +class C { + operator fun get(i: Int): C = this + operator fun set(i: Int, v: String) {} + operator fun plusAssign(a: () -> Unit) {} + operator fun plus(v: () -> Unit) {} +} + +fun test_3(x: C) { + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + Unit + } + } +} + +// both fit +class D { + operator fun set(i: Int, x: D) {} + operator fun get(i: Int): D = this + operator fun plusAssign(x: () -> Unit) {} + operator fun plus(v: () -> Unit): D = this +} + +fun test_4(x: D) { + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + Unit + } + } +} + +// nothing fit +class E + +fun test_5(x: E) { + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + Unit + } + } +} + + +// only plus, plusAssign doesn't fir because of lambda +class F { + operator fun set(i: Int, x: F) {} + operator fun get(i: Int): F = this + operator fun plusAssign(x: () -> String) {} + operator fun plus(v: () -> Int): F = this +} + +fun test_6(x: F) { + x[1] += { + someCallInsideLambda() + "please choose String" + } +} + +// only plus, no set. 3 indices in get/set +class G { + operator fun get(i: Int, j: Int, k: Int): G = this + operator fun set(i: Int, j: Int, k: Int, x: G) {} + operator fun plus(v: () -> Unit): G = this +} + +fun test_7(x: G) { + x[1, 2, 3] += { + someCallInsideLambda() + x[1, 2, 3] += { + someCallInsideLambda() + Unit + } + } +} + +fun someCallInsideLambda() {} diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.fir.txt b/compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.fir.txt new file mode 100644 index 00000000000..3e1655f4dcd --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.fir.txt @@ -0,0 +1,162 @@ +FILE: exponentialArraySetWithPlusAssign.kt + public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + public final operator fun get(i: R|kotlin/Int|): R|A| { + ^get this@R|/A| + } + + public final operator fun plusAssign(v: R|() -> kotlin/Unit|): R|kotlin/Unit| { + } + + } + public final fun test_1(x: R|A|): R|kotlin/Unit| { + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/A.get|(Int(1)).R|/A.plusAssign|(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + Q|kotlin/Unit| + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + public final class D : R|kotlin/Any| { + public constructor(): R|D| { + super() + } + + public final operator fun set(i: R|kotlin/Int|, x: R|D|): R|kotlin/Unit| { + } + + public final operator fun get(i: R|kotlin/Int|): R|D| { + ^get this@R|/D| + } + + public final operator fun plusAssign(x: R|() -> kotlin/Unit|): R|kotlin/Unit| { + } + + public final operator fun plus(v: R|() -> kotlin/Unit|): R|D| { + ^plus this@R|/D| + } + + } + public final fun test_2(x: R|D|): R|kotlin/Unit| { + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + R|/x|.R|/D.get|(Int(1)).#(fun (): R|kotlin/Unit| { + R|/someCallInsideLambda|() + Q|kotlin/Unit| + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + ) + } + public final fun someCallInsideLambda(): R|kotlin/Unit| { + } diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.kt b/compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.kt new file mode 100644 index 00000000000..d3deb6a0c69 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.kt @@ -0,0 +1,116 @@ +// ISSUE: KT-50861 + +// only plusAssign, no set +class A { + operator fun get(i: Int): A = this + operator fun plusAssign(v: () -> Unit) {} +} + +fun test_1(x: A) { + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + Unit + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} + + +// both fit +class D { + operator fun set(i: Int, x: D) {} + operator fun get(i: Int): D = this + operator fun plusAssign(x: () -> Unit) {} + operator fun plus(v: () -> Unit): D = this +} + +fun test_2(x: D) { + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + x[1] += { + someCallInsideLambda() + Unit + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} + +fun someCallInsideLambda() {} diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/operators/plusAndPlusAssign.kt b/compiler/fir/analysis-tests/testData/resolve/expresssions/operators/plusAndPlusAssign.kt index e82fac51f7d..57079c49b7c 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/operators/plusAndPlusAssign.kt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/operators/plusAndPlusAssign.kt @@ -5,5 +5,5 @@ class Foo { fun test() { var f = Foo() - f += f + f += f } diff --git a/compiler/fir/analysis-tests/testData/resolve/extendedCheckers/CanBeValChecker.kt b/compiler/fir/analysis-tests/testData/resolve/extendedCheckers/CanBeValChecker.kt index 0dfc3cb3763..5d155809621 100644 --- a/compiler/fir/analysis-tests/testData/resolve/extendedCheckers/CanBeValChecker.kt +++ b/compiler/fir/analysis-tests/testData/resolve/extendedCheckers/CanBeValChecker.kt @@ -24,7 +24,7 @@ fun testOperatorAssignment() { val c = C() c += "" var c1 = C() - c1 += "" + c1 += "" var a = 1 a += 12 diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 1771d428579..5624eff54d9 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -863,6 +863,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/callResolution"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("arraySetWithPlusAssign.kt") + public void testArraySetWithPlusAssign() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.kt"); + } + @Test @TestMetadata("companionInvoke.kt") public void testCompanionInvoke() throws Exception { @@ -893,6 +899,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt"); } + @Test + @TestMetadata("exponentialArraySetWithPlusAssign.kt") + public void testExponentialArraySetWithPlusAssign() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.kt"); + } + @Test @TestMetadata("extensionInvokeAfterSafeCall.kt") public void testExtensionInvokeAfterSafeCall() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index 460ed779361..2347f5449e7 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -863,6 +863,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/callResolution"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("arraySetWithPlusAssign.kt") + public void testArraySetWithPlusAssign() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/arraySetWithPlusAssign.kt"); + } + @Test @TestMetadata("companionInvoke.kt") public void testCompanionInvoke() throws Exception { @@ -893,6 +899,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt"); } + @Test + @TestMetadata("exponentialArraySetWithPlusAssign.kt") + public void testExponentialArraySetWithPlusAssign() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/exponentialArraySetWithPlusAssign.kt"); + } + @Test @TestMetadata("extensionInvokeAfterSafeCall.kt") public void testExtensionInvokeAfterSafeCall() throws Exception { diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 92e5043b2c0..3c0d8544940 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -518,7 +518,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val OVERLOAD_RESOLUTION_AMBIGUITY by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { parameter>("candidates") } - val ASSIGN_OPERATOR_AMBIGUITY by error { + val ASSIGN_OPERATOR_AMBIGUITY by error(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) { parameter>("candidates") } val ITERATOR_AMBIGUITY by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 49a02a342c6..149ab8076ee 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -351,7 +351,7 @@ object FirErrors { // Ambiguity val OVERLOAD_RESOLUTION_AMBIGUITY by error1>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) - val ASSIGN_OPERATOR_AMBIGUITY by error1>>() + val ASSIGN_OPERATOR_AMBIGUITY by error1>>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val ITERATOR_AMBIGUITY by error1>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val HAS_NEXT_FUNCTION_AMBIGUITY by error1>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val NEXT_AMBIGUITY by error1>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt index 686bdffce00..8afaa7c55b8 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -1058,14 +1058,6 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte null, ConeSimpleDiagnostic("No value for array set", DiagnosticKind.Syntax) ) - // Second copy of rhs is used because we analyze it twice in different contexts - // and now they should be different expressions instances to make everything work properly. - // But this lead to exponential time already at FIR building stage, - // so we hope this hack will be removed with KT-50861 - this.rhs2 = rhs?.convert() ?: buildErrorExpression( - null, - ConeSimpleDiagnostic("No value for array set", DiagnosticKind.Syntax) - ) this.arrayAccessSource = arrayAccessSource this.annotations += annotations } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index eceebef36a7..844e199db23 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve import org.jetbrains.kotlin.KtFakeSourceElementKind +import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fakeElement import org.jetbrains.kotlin.fir.* @@ -25,7 +26,6 @@ import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.* -import org.jetbrains.kotlin.fir.resolve.dfa.coneType import org.jetbrains.kotlin.fir.resolve.dfa.unwrapSmartcastExpression import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.inference.FirStubInferenceSession @@ -46,7 +46,6 @@ import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor -import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.types.TypeApproximatorConfiguration @@ -516,28 +515,17 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform assignmentOperatorStatement: FirAssignmentOperatorStatement, data: ResolutionMode ): FirStatement { - require(assignmentOperatorStatement.operation != FirOperation.ASSIGN) + val operation = assignmentOperatorStatement.operation + require(operation != FirOperation.ASSIGN) assignmentOperatorStatement.transformAnnotations(transformer, ResolutionMode.ContextIndependent) val leftArgument = assignmentOperatorStatement.leftArgument.transformSingle(transformer, ResolutionMode.ContextIndependent) val rightArgument = assignmentOperatorStatement.rightArgument.transformSingle(transformer, ResolutionMode.ContextDependent) - fun createFunctionCall(name: Name): FirFunctionCall = buildFunctionCall { - source = assignmentOperatorStatement.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) - explicitReceiver = leftArgument - argumentList = buildUnaryArgumentList(rightArgument) - calleeReference = buildSimpleNamedReference { - // TODO: Use source of operator for callee reference source - source = assignmentOperatorStatement.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) - this.name = name - candidateSymbol = null - } - origin = FirFunctionCallOrigin.Operator - } + val generator = GeneratorOfPlusAssignCalls(assignmentOperatorStatement, operation, leftArgument, rightArgument) // x.plusAssign(y) - val assignmentOperatorName = FirOperationNameConventions.ASSIGNMENTS.getValue(assignmentOperatorStatement.operation) - val assignOperatorCall = createFunctionCall(assignmentOperatorName) + val assignOperatorCall = generator.createAssignOperatorCall() val resolvedAssignCall = resolveCandidateForAssignmentOperatorCall { assignOperatorCall.transformSingle(this, ResolutionMode.ContextDependent) } @@ -545,8 +533,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform val assignIsSuccessful = assignCallReference?.isError == false // x = x + y - val simpleOperatorName = FirOperationNameConventions.ASSIGNMENTS_TO_SIMPLE_OPERATOR.getValue(assignmentOperatorStatement.operation) - val simpleOperatorCall = createFunctionCall(simpleOperatorName) + val simpleOperatorCall = generator.createSimpleOperatorCall() val resolvedOperatorCall = resolveCandidateForAssignmentOperatorCall { simpleOperatorCall.transformSingle(this, ResolutionMode.ContextDependent) } @@ -1118,90 +1105,155 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform } } + private class GeneratorOfPlusAssignCalls( + val baseElement: FirStatement, + val operation: FirOperation, + val lhs: FirExpression, + val rhs: FirExpression + ) { + companion object { + fun createFunctionCall( + name: Name, + source: KtSourceElement?, + receiver: FirExpression, + vararg arguments: FirExpression + ): FirFunctionCall = buildFunctionCall { + this.source = source + explicitReceiver = receiver + argumentList = when(arguments.size) { + 0 -> FirEmptyArgumentList + 1 -> buildUnaryArgumentList(arguments.first()) + else -> buildArgumentList { + this.arguments.addAll(arguments) + } + } + calleeReference = buildSimpleNamedReference { + // TODO: Use source of operator for callee reference source + this.source = source + this.name = name + candidateSymbol = null + } + origin = FirFunctionCallOrigin.Operator + } + } + + private fun createFunctionCall(name: Name): FirFunctionCall { + return createFunctionCall(name, baseElement.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment), lhs, rhs) + } + + fun createAssignOperatorCall(): FirFunctionCall { + return createFunctionCall(FirOperationNameConventions.ASSIGNMENTS.getValue(operation)) + } + + fun createSimpleOperatorCall(): FirFunctionCall { + return createFunctionCall(FirOperationNameConventions.ASSIGNMENTS_TO_SIMPLE_OPERATOR.getValue(operation)) + } + } + @OptIn(ExperimentalStdlibApi::class) override fun transformAugmentedArraySetCall( augmentedArraySetCall: FirAugmentedArraySetCall, data: ResolutionMode ): FirStatement { - assert(augmentedArraySetCall.operation in FirOperation.ASSIGNMENTS) - assert(augmentedArraySetCall.operation != FirOperation.ASSIGN) + /* + * a[b] += c can be desugared to: + * + * 1. a.get(b).plusAssign(c) + * 2. a.set(b, a.get(b).plus(c)) + */ + + val operation = augmentedArraySetCall.operation + assert(operation in FirOperation.ASSIGNMENTS) + assert(operation != FirOperation.ASSIGN) augmentedArraySetCall.transformAnnotations(transformer, data) - val operatorName = FirOperationNameConventions.ASSIGNMENTS.getValue(augmentedArraySetCall.operation) - val transformedLhsCall = - augmentedArraySetCall.lhsGetCall.transformSingle(transformer, ResolutionMode.ContextIndependent).takeIf { it.isSuccessful() } + // transformedLhsCall: a.get(index) + val transformedLhsCall = augmentedArraySetCall.lhsGetCall.transformSingle(transformer, ResolutionMode.ContextIndependent) + val transformedRhs = augmentedArraySetCall.rhs.transformSingle(transformer, ResolutionMode.ContextDependent) - val blockForGetSetVersion: FirBlock? = - transformedLhsCall?.let { augmentedArraySetCall.tryResolveAugmentedArraySetCallAsSetGetBlock(it) } - val assignResolvedCall: FirFunctionCall? = - transformedLhsCall?.let { augmentedArraySetCall.tryResolveWithOperatorAssignConvention(it) } + val generator = GeneratorOfPlusAssignCalls(augmentedArraySetCall, operation, transformedLhsCall, transformedRhs) - val result: FirStatement = when { - assignResolvedCall != null && blockForGetSetVersion != null -> { - augmentedArraySetCall.also { - it.replaceCalleeReference( - buildErrorNamedReference { - // TODO: add better diagnostic - source = augmentedArraySetCall.source - diagnostic = ConeAmbiguityError(operatorName, CandidateApplicability.RESOLVED, emptyList()) - } - ) - } - } - blockForGetSetVersion != null -> { - //checking secondResult leave erroneous nodes in dfa graph, - //we add another block so final type of expression will be correct - //todo replace this hack with proper graph cleaning - transformer.components.dataFlowAnalyzer.enterBlock(blockForGetSetVersion) - transformer.components.dataFlowAnalyzer.exitBlock(blockForGetSetVersion) - blockForGetSetVersion - } - assignResolvedCall != null -> assignResolvedCall - else -> { - augmentedArraySetCall.rhs.transformSingle(transformer, ResolutionMode.ContextIndependent) - augmentedArraySetCall.rhs2.transformSingle(transformer, ResolutionMode.ContextIndependent) - - augmentedArraySetCall.also { - it.replaceCalleeReference( - buildErrorNamedReference { - source = augmentedArraySetCall.source - diagnostic = ConeUnresolvedNameError(operatorName) - } - ) - } - } + // a.get(b).plusAssign(c) + val assignOperatorCall = generator.createAssignOperatorCall() + val resolvedAssignCall = resolveCandidateForAssignmentOperatorCall { + assignOperatorCall.transformSingle(this, ResolutionMode.ContextDependent) } - return result - } + val assignCallReference = resolvedAssignCall.calleeReference as? FirNamedReferenceWithCandidate + val assignIsSuccessful = assignCallReference?.isError == false - private fun FirFunctionCall.isSuccessful(): Boolean = - typeRef !is FirErrorTypeRef && calleeReference is FirResolvedNamedReference + // .set(, .get().plus(c)) + val info = tryResolveAugmentedArraySetCallAsSetGetBlock(augmentedArraySetCall, transformedLhsCall, transformedRhs) + val resolvedOperatorCall = info.operatorCall + val operatorCallReference = resolvedOperatorCall.calleeReference as? FirNamedReferenceWithCandidate + val operatorIsSuccessful = operatorCallReference?.isError == false - - /** - * Desugarings of a[x, y] += z to - * a.get(x, y).plusAssign(z) - * - * @return null if `plusAssign` is unresolved - * @return block defined as described above, otherwise - */ - private fun FirAugmentedArraySetCall.tryResolveWithOperatorAssignConvention(lhsGetCall: FirFunctionCall): FirFunctionCall? { - val assignCall = buildFunctionCall { - source = this@tryResolveWithOperatorAssignConvention.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) - calleeReference = buildSimpleNamedReference { - name = FirOperationNameConventions.ASSIGNMENTS.getValue(operation) - } - explicitReceiver = lhsGetCall - argumentList = buildArgumentList { - arguments += rhs2 - } - origin = FirFunctionCallOrigin.Operator - annotations += this@tryResolveWithOperatorAssignConvention.annotations + fun completeAssignCall() { + dataFlowAnalyzer.enterFunctionCall(resolvedAssignCall) + callCompleter.completeCall(resolvedAssignCall, noExpectedType) + dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true) } - val transformedCall = assignCall.transformSingle(transformer, ResolutionMode.ContextIndependent) - return transformedCall.takeIf { it.isSuccessful() } + fun chooseAssign(): FirStatement { + completeAssignCall() + return resolvedAssignCall + } + + // if `plus` call already inapplicable then there is no need to try to resolve `set` call + if (assignIsSuccessful && !operatorIsSuccessful) { + return chooseAssign() + } + + // a.set(b, a.get(b).plus(c)) + val resolvedSetCall = info.setCall + val setCallReference = resolvedSetCall.calleeReference as? FirNamedReferenceWithCandidate + val setIsSuccessful = setCallReference?.isError == false + + fun chooseSetOperator(): FirStatement { + dataFlowAnalyzer.enterFunctionCall(resolvedSetCall) + dataFlowAnalyzer.enterFunctionCall(resolvedOperatorCall) + callCompleter.completeCall( + resolvedSetCall, + noExpectedType, + expectedTypeMismatchIsReportedInChecker = true + ) + dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true) + dataFlowAnalyzer.exitFunctionCall(resolvedSetCall, callCompleted = true) + return info.toBlock() + } + + fun reportError(diagnostic: ConeDiagnostic): FirStatement { + completeAssignCall() + val errorReference = buildErrorNamedReference { + source = augmentedArraySetCall.source + this.diagnostic = diagnostic + } + resolvedAssignCall.replaceCalleeReference(errorReference) + + return resolvedAssignCall + } + + fun reportAmbiguity( + firstReference: FirNamedReferenceWithCandidate?, + secondReference: FirNamedReferenceWithCandidate? + ): FirStatement { + val firstCandidate = firstReference?.candidate + val secondCandidate = secondReference?.candidate + requireNotNull(firstCandidate) + requireNotNull(secondCandidate) + return reportError(ConeOperatorAmbiguityError(listOf(firstCandidate, secondCandidate))) + } + + fun reportUnresolvedReference(): FirStatement { + return reportError(ConeUnresolvedNameError(Name.identifier(operation.operator))) + } + + return when { + assignIsSuccessful && setIsSuccessful -> reportAmbiguity(assignCallReference, setCallReference) + assignIsSuccessful -> chooseAssign() + setIsSuccessful -> chooseSetOperator() + else -> reportUnresolvedReference() + } } /** @@ -1216,15 +1268,41 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform * @return null if `set` or `plus` calls are unresolved * @return block defined as described above, otherwise */ - private fun FirAugmentedArraySetCall.tryResolveAugmentedArraySetCallAsSetGetBlock(lhsGetCall: FirFunctionCall): FirBlock? { + private inner class AugmentedArraySetAsGetSetCallDesugaringInfo( + val augmentedArraySetCall: FirAugmentedArraySetCall, + val arrayVariable: FirProperty, + val indexVariables: List, + val operatorCall: FirFunctionCall, + val setCall: FirFunctionCall + ) { + fun toBlock(): FirBlock { + return buildBlock { + annotations += augmentedArraySetCall.annotations + statements += arrayVariable + statements += indexVariables + statements += setCall + }.also { + it.replaceTypeRef( + buildResolvedTypeRef { + type = session.builtinTypes.unitType.type + } + ) + } + } + } + + private fun tryResolveAugmentedArraySetCallAsSetGetBlock( + augmentedArraySetCall: FirAugmentedArraySetCall, + lhsGetCall: FirFunctionCall, + transformedRhs: FirExpression + ): AugmentedArraySetAsGetSetCallDesugaringInfo { val arrayVariable = generateTemporaryVariable( session.moduleData, - source = null, + source = lhsGetCall.explicitReceiver?.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment), specialName = "", initializer = lhsGetCall.explicitReceiver ?: buildErrorExpression { - source = - this@tryResolveAugmentedArraySetCallAsSetGetBlock.source - ?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) + source = augmentedArraySetCall.source + ?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) diagnostic = ConeSimpleDiagnostic("No receiver for array access", DiagnosticKind.Syntax) } ) @@ -1235,88 +1313,78 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform else listOf(it) }.mapIndexed { i, index -> - generateTemporaryVariable(session.moduleData, source = null, specialName = "", initializer = index) - } - - val getCall = buildFunctionCall { - source = arrayAccessSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) - explicitReceiver = arrayVariable.toQualifiedAccess() - calleeReference = buildSimpleNamedReference { - name = OperatorNameConventions.GET - } - argumentList = buildArgumentList { - for (indexVariable in indexVariables) { - arguments += indexVariable.toQualifiedAccess() - } - } - origin = FirFunctionCallOrigin.Operator - } - - val operatorCall = buildFunctionCall { - calleeReference = buildSimpleNamedReference { - name = FirOperationNameConventions.ASSIGNMENTS_TO_SIMPLE_OPERATOR.getValue(operation) - } - explicitReceiver = getCall - argumentList = buildArgumentList { - arguments += rhs - } - origin = FirFunctionCallOrigin.Operator - } - - val setCall = buildFunctionCall { - source = - this@tryResolveAugmentedArraySetCallAsSetGetBlock.source - ?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) - explicitReceiver = arrayVariable.toQualifiedAccess() - calleeReference = buildSimpleNamedReference { - name = OperatorNameConventions.SET - } - origin = FirFunctionCallOrigin.Operator - argumentList = buildArgumentList { - for (indexVariable in indexVariables) { - arguments += indexVariable.toQualifiedAccess() - } - - arguments += operatorCall - } - - annotations += this@tryResolveAugmentedArraySetCallAsSetGetBlock.annotations + generateTemporaryVariable( + session.moduleData, + source = index.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment), + specialName = "", + initializer = index + ) } arrayVariable.transformSingle(transformer, ResolutionMode.ContextIndependent) indexVariables.forEach { it.transformSingle(transformer, ResolutionMode.ContextIndependent) } - val transformedSet = setCall.transformSingle(transformer, ResolutionMode.ContextIndependent) - if (!transformedSet.isSuccessful()) return null + val arrayAccess = arrayVariable.toQualifiedAccess() + val indicesQualifiedAccess = indexVariables.map { it.toQualifiedAccess() } - val transformedOperator = - transformedSet.argumentList.arguments.last().let { - if (it is FirNamedArgumentExpression) - it.expression - else - it + val getCall = buildFunctionCall { + source = augmentedArraySetCall.arrayAccessSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) + explicitReceiver = arrayAccess + if (lhsGetCall.explicitReceiver == lhsGetCall.dispatchReceiver) { + dispatchReceiver = arrayAccess + extensionReceiver = lhsGetCall.extensionReceiver + } else { + extensionReceiver = arrayAccess + dispatchReceiver = lhsGetCall.dispatchReceiver } - - require(transformedOperator is FirFunctionCall) { - "Last argument of set call should be an operator but $transformedOperator found" - } - - if (!transformedOperator.isSuccessful()) return null - - return buildBlock { - statements += arrayVariable - statements += indexVariables - statements += setCall - }.also { - it.replaceTypeRef( - buildResolvedTypeRef { - source = this@tryResolveAugmentedArraySetCallAsSetGetBlock.source - type = session.builtinTypes.unitType.type + calleeReference = lhsGetCall.calleeReference + argumentList = buildArgumentList { + var i = 0 + for (argument in lhsGetCall.argumentList.arguments) { + arguments += if (argument is FirVarargArgumentsExpression) { + buildVarargArgumentsExpression { + val varargSize = argument.arguments.size + arguments += indicesQualifiedAccess.subList(i, i + varargSize) + i += varargSize + source = argument.source + typeRef = argument.typeRef + varargElementType = argument.varargElementType + } + } else { + indicesQualifiedAccess[i++] + } } - ) + } + origin = FirFunctionCallOrigin.Operator + typeRef = lhsGetCall.typeRef } - } + val generator = GeneratorOfPlusAssignCalls(augmentedArraySetCall, augmentedArraySetCall.operation, getCall, transformedRhs) + + val operatorCall = generator.createSimpleOperatorCall() + val resolvedOperatorCall = resolveCandidateForAssignmentOperatorCall { + operatorCall.transformSingle(this, ResolutionMode.ContextDependent) + } + + val setCall = GeneratorOfPlusAssignCalls.createFunctionCall( + OperatorNameConventions.SET, + augmentedArraySetCall.source, + receiver = arrayAccess, // a + *indicesQualifiedAccess.toTypedArray(), // indices + resolvedOperatorCall // a.get(b).plus(c) + ) + val resolvedSetCall = resolveCandidateForAssignmentOperatorCall { + setCall.transformSingle(this, ResolutionMode.ContextDependent) + } + + return AugmentedArraySetAsGetSetCallDesugaringInfo( + augmentedArraySetCall, + arrayVariable, + indexVariables, + resolvedOperatorCall, + resolvedSetCall + ) + } override fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: ResolutionMode): FirStatement { if (data is ResolutionMode.ContextDependent) { diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAugmentedArraySetCall.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAugmentedArraySetCall.kt index f8cc9ae6898..ef5ca66fca7 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAugmentedArraySetCall.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAugmentedArraySetCall.kt @@ -21,7 +21,6 @@ abstract class FirAugmentedArraySetCall : FirPureAbstractElement(), FirStatement abstract override val annotations: List abstract val lhsGetCall: FirFunctionCall abstract val rhs: FirExpression - abstract val rhs2: FirExpression abstract val operation: FirOperation abstract val calleeReference: FirReference abstract val arrayAccessSource: KtSourceElement? diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirAugmentedArraySetCallBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirAugmentedArraySetCallBuilder.kt index 8f14e1763ad..181567c218e 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirAugmentedArraySetCallBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirAugmentedArraySetCallBuilder.kt @@ -30,7 +30,6 @@ class FirAugmentedArraySetCallBuilder : FirAnnotationContainerBuilder { override val annotations: MutableList = mutableListOf() lateinit var lhsGetCall: FirFunctionCall lateinit var rhs: FirExpression - lateinit var rhs2: FirExpression lateinit var operation: FirOperation var calleeReference: FirReference = FirStubReference var arrayAccessSource: KtSourceElement? = null @@ -41,7 +40,6 @@ class FirAugmentedArraySetCallBuilder : FirAnnotationContainerBuilder { annotations, lhsGetCall, rhs, - rhs2, operation, calleeReference, arrayAccessSource, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAugmentedArraySetCallImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAugmentedArraySetCallImpl.kt index a6ee7711f07..1038b9ec317 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAugmentedArraySetCallImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAugmentedArraySetCallImpl.kt @@ -24,7 +24,6 @@ internal class FirAugmentedArraySetCallImpl( override val annotations: MutableList, override var lhsGetCall: FirFunctionCall, override var rhs: FirExpression, - override var rhs2: FirExpression, override val operation: FirOperation, override var calleeReference: FirReference, override val arrayAccessSource: KtSourceElement?, @@ -33,7 +32,6 @@ internal class FirAugmentedArraySetCallImpl( annotations.forEach { it.accept(visitor, data) } lhsGetCall.accept(visitor, data) rhs.accept(visitor, data) - rhs2.accept(visitor, data) calleeReference.accept(visitor, data) } @@ -41,7 +39,6 @@ internal class FirAugmentedArraySetCallImpl( transformAnnotations(transformer, data) lhsGetCall = lhsGetCall.transform(transformer, data) rhs = rhs.transform(transformer, data) - rhs2 = rhs2.transform(transformer, data) calleeReference = calleeReference.transform(transformer, data) return this } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirGeneration.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirGeneration.kt index 1533781465b..9cbb6968097 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirGeneration.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirGeneration.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fakeElement import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl @@ -25,11 +26,14 @@ import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef import org.jetbrains.kotlin.name.Name fun FirVariable.toQualifiedAccess(): FirQualifiedAccessExpression = buildPropertyAccessExpression { + val fakeSource = this@toQualifiedAccess.source?.fakeElement(KtFakeSourceElementKind.ReferenceInAtomicQualifiedAccess) + source = fakeSource calleeReference = buildResolvedNamedReference { - source = this@toQualifiedAccess.source?.fakeElement(KtFakeSourceElementKind.ReferenceInAtomicQualifiedAccess) + source = fakeSource name = this@toQualifiedAccess.name resolvedSymbol = this@toQualifiedAccess.symbol } + typeRef = this@toQualifiedAccess.returnTypeRef } fun generateTemporaryVariable( @@ -39,7 +43,7 @@ fun generateTemporaryVariable( initializer: FirExpression, typeRef: FirTypeRef? = null, extractedAnnotations: Collection? = null, -): FirVariable = +): FirProperty = buildProperty { this.source = source this.moduleData = moduleData @@ -66,7 +70,7 @@ fun generateTemporaryVariable( specialName: String, initializer: FirExpression, extractedAnnotations: Collection? = null, -): FirVariable = +): FirProperty = generateTemporaryVariable( moduleData, source, diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index 41208b9130f..17d726e7f3b 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -463,7 +463,6 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild augmentedArraySetCall.configure { +field("lhsGetCall", functionCall) +field("rhs", expression) - +field("rhs2", expression) +field("operation", operationType) // Used for resolution errors reporting in case +field("calleeReference", reference, withReplace = true) diff --git a/compiler/testData/diagnostics/tests/callableReference/compatibilityResolveWithVarargAndOperatorCall.kt b/compiler/testData/diagnostics/tests/callableReference/compatibilityResolveWithVarargAndOperatorCall.kt index 821c47c5809..33d98ac9f5c 100644 --- a/compiler/testData/diagnostics/tests/callableReference/compatibilityResolveWithVarargAndOperatorCall.kt +++ b/compiler/testData/diagnostics/tests/callableReference/compatibilityResolveWithVarargAndOperatorCall.kt @@ -16,4 +16,4 @@ fun withVararg(vararg xs: Int) = 42 fun test1() { A[::withVararg] += 1 -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInArrayAccess.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInArrayAccess.fir.kt index a6d1bce63f6..e4d50e52ac7 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInArrayAccess.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInArrayAccess.fir.kt @@ -34,7 +34,7 @@ fun testArrayAssignment4(n: Nothing) { fun testArrayPlusAssign(array: Array) { operator fun Any.plusAssign(a: Any) {} - array[1] += todo() + array[1] += todo() } fun todo(): Nothing = throw Exception() diff --git a/compiler/testData/diagnostics/tests/operatorRem/remAndRemAssignAmbiguity.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/remAndRemAssignAmbiguity.fir.kt deleted file mode 100644 index 4f0bc9ff038..00000000000 --- a/compiler/testData/diagnostics/tests/operatorRem/remAndRemAssignAmbiguity.fir.kt +++ /dev/null @@ -1,12 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER - -object RemAndRemAssign { - operator fun rem(x: Int) = RemAndRemAssign -} - -operator fun RemAndRemAssign.remAssign(x: Int) {} - -fun test() { - var c = RemAndRemAssign - c %= 1 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/operatorRem/remAndRemAssignAmbiguity.kt b/compiler/testData/diagnostics/tests/operatorRem/remAndRemAssignAmbiguity.kt index 4ddbf434745..2fbdd31554f 100644 --- a/compiler/testData/diagnostics/tests/operatorRem/remAndRemAssignAmbiguity.kt +++ b/compiler/testData/diagnostics/tests/operatorRem/remAndRemAssignAmbiguity.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER object RemAndRemAssign { diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/AssignOperatorAmbiguity.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/AssignOperatorAmbiguity.fir.kt deleted file mode 100644 index 2fcd95faf7b..00000000000 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/AssignOperatorAmbiguity.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -//KT-1820 Write test for ASSIGN_OPERATOR_AMBIGUITY -package kt1820 - -class MyInt(val i: Int) { - operator fun plus(m: MyInt) : MyInt = MyInt(m.i + i) -} - -operator fun Any.plusAssign(a: Any) {} - -fun test(m: MyInt) { - m += m - - var i = 1 - i += 34 -} - - diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/AssignOperatorAmbiguity.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/AssignOperatorAmbiguity.kt index 4b4a9d81557..2fa7eff328d 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/AssignOperatorAmbiguity.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/AssignOperatorAmbiguity.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL //KT-1820 Write test for ASSIGN_OPERATOR_AMBIGUITY package kt1820 diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/InconsistentGetSet.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/InconsistentGetSet.fir.kt index 66880ac154d..8cf34a1bfa6 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/InconsistentGetSet.fir.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/InconsistentGetSet.fir.kt @@ -40,6 +40,6 @@ fun testMismatchingArities() { ++MismatchingArities2[0] MismatchingArities2[0]++ - MismatchingArities2[0] += 1 + MismatchingArities2[0] += 1 } diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.fir.kt deleted file mode 100644 index 08d33f67b5f..00000000000 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.fir.kt +++ /dev/null @@ -1,20 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER - -class C { - operator fun get(i: Int): C = this -} - -operator fun C.plus(a: Any): C = this -operator fun C.plusAssign(a: Any) {} - -class C1 { - operator fun get(i: Int): C = C() - operator fun set(i: Int, v: C) {} -} - -fun test() { - val c = C() - c[0] += "" - var c1 = C1() - c1[0] += "" -} diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.kt index 6d4ad857ee8..9cf101b9d9f 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER class C { diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnLocal.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnLocal.fir.kt deleted file mode 100644 index 4063b709120..00000000000 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnLocal.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER - -class C - -operator fun C.plus(a: Any): C = this -operator fun C.plusAssign(a: Any) {} - -fun test() { - val c = C() - c += "" - var c1 = C() - c1 += "" -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnLocal.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnLocal.kt index f4ee40b166b..c2476d39462 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnLocal.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnLocal.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER class C diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnProperty.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnProperty.fir.kt deleted file mode 100644 index fc1bb6297da..00000000000 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnProperty.fir.kt +++ /dev/null @@ -1,19 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER - -class C { - val c: C = C() -} - -operator fun C.plus(a: Any): C = this -operator fun C.plusAssign(a: Any) {} - -class C1 { - var c: C = C() -} - -fun test() { - val c = C() - c.c += "" - var c1 = C1() - c1.c += "" -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnProperty.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnProperty.kt index 3717b5046c1..3ab3e5df043 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnProperty.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnProperty.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER class C { diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/plusAssignWithLambda2.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/plusAssignWithLambda2.fir.kt index 29dc106bc45..9d98f2352a6 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/plusAssignWithLambda2.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/plusAssignWithLambda2.fir.kt @@ -13,8 +13,8 @@ fun id(x: T) = x fun main() { var newValue = A() - newValue += id { total -> A() } - newValue += id(fun(total) = A()) - newValue += id(fun(total): A { return A() }) - newValue += id(::foo) + newValue += id { total -> A() } + newValue += id(fun(total) = A()) + newValue += id(fun(total): A { return A() }) + newValue += id(::foo) } diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-4/pos/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-4/pos/1.1.fir.kt index 89339c58e49..15f04316802 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-4/pos/1.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-4/pos/1.1.fir.kt @@ -20,14 +20,14 @@ class B() { fun case7(){ var b =B() - b+=1 //ASSIGN_OPERATOR_AMBIGUITY + b+=1 //ASSIGN_OPERATOR_AMBIGUITY this += 1 //ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT, PROPERTY_AS_OPERATOR } } fun case1() { var b = B() - b += 1 //ASSIGN_OPERATOR_AMBIGUITY + b += 1 //ASSIGN_OPERATOR_AMBIGUITY } // FILE: TestCase2.kt @@ -52,7 +52,7 @@ class B() { b += 1 //ok var b1 = B() - b1 += 1 //ASSIGN_OPERATOR_AMBIGUITY + b1 += 1 //ASSIGN_OPERATOR_AMBIGUITY this += 1 //ok } @@ -60,5 +60,5 @@ class B() { fun case2() { var b = B() - b += 1 //ASSIGN_OPERATOR_AMBIGUITY + b += 1 //ASSIGN_OPERATOR_AMBIGUITY } diff --git a/compiler/tests-spec/testData/diagnostics/linked/statements/assignments/operator-assignments/p-2/neg/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/statements/assignments/operator-assignments/p-2/neg/1.1.fir.kt index a79d5a3f920..4fc8281b2bd 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/statements/assignments/operator-assignments/p-2/neg/1.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/statements/assignments/operator-assignments/p-2/neg/1.1.fir.kt @@ -15,5 +15,5 @@ class B(var a: Int) { // TESTCASE NUMBER: 1 fun case1() { var b = B(1) - b += 1 + b += 1 } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/13.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/13.fir.kt index ce6778e7f9f..290eb0b6afa 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/13.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/13.fir.kt @@ -5,7 +5,7 @@ // TESTCASE NUMBER: 1 fun case_1(x: Class?) { x!! - x[if (true) {x=null;0} else 0] += x[0] + x[if (true) {x=null;0} else 0] += x[0] x x[0].inv() } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/26.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/26.fir.kt index 1d2f7ad379d..c4177407b14 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/26.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/26.fir.kt @@ -10,7 +10,7 @@ fun case_1() { var x: MutableList? = mutableListOf(1) x!! - ? & kotlin.collections.MutableList")!>x[if (true) {x=null;0} else 0] += ?")!>x[0] + ? & kotlin.collections.MutableList")!>x[if (true) {x=null;0} else 0] += ?")!>x[0] ?")!>x ?")!>x[0].inv() }