diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 1797cb1efda..dd49a5972e0 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -13011,6 +13011,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/increment/classNaryGetSet.kt"); } + @TestMetadata("classVarargGetSet.kt") + public void testClassVarargGetSet() throws Exception { + runTest("compiler/testData/codegen/box/increment/classVarargGetSet.kt"); + } + @TestMetadata("classWithGetSet.kt") public void testClassWithGetSet() throws Exception { runTest("compiler/testData/codegen/box/increment/classWithGetSet.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt index 3b28df7f6e4..fe761814ab6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt @@ -104,6 +104,7 @@ class Candidate( var argumentMapping: Map? = null var numDefaults: Int = 0 + var oldToNewArgumentMapping: Map? = null lateinit var typeArgumentMapping: TypeArgumentMapping val postponedAtoms = mutableListOf() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirArgumentsToParametersMapper.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirArgumentsToParametersMapper.kt index 5e86ad0cdf1..00c769f6db6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirArgumentsToParametersMapper.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirArgumentsToParametersMapper.kt @@ -30,6 +30,7 @@ data class ArgumentMapping( // foo(b = bar(), a = qux()) // parameterToCallArgumentMap.values() should be [ 'bar()', 'foo()' ] val parameterToCallArgumentMap: Map, + val oldToNewArgumentMap: Map, val diagnostics: List ) { fun toArgumentToParameterMapping(): Map { @@ -50,7 +51,7 @@ data class ArgumentMapping( } } -private val EmptyArgumentMapping = ArgumentMapping(emptyMap(), emptyList()) +private val EmptyArgumentMapping = ArgumentMapping(emptyMap(), emptyMap(), emptyList()) fun BodyResolveComponents.mapArguments( arguments: List, @@ -67,11 +68,12 @@ fun BodyResolveComponents.mapArguments( arguments.subList(0, arguments.size - 1) } - // If this is an overloading indexed access operator, it could have default values in the middle. + // If this is an overloading indexed access operator, it could have default values or a vararg parameter in the middle. // For proper argument mapping, wrap the last one, which is supposed to be the updated value, as a named argument. + val oldToNewArgumentMap = mutableMapOf() if ((function as? FirSimpleFunction)?.isOperator == true && function.name == Name.identifier("set") && - function.valueParameters.any { it.defaultValue != null } + function.valueParameters.any { it.defaultValue != null || it.isVararg } ) { val v = argumentsInParenthesis.last() if (v !is FirNamedArgumentExpression) { @@ -82,6 +84,7 @@ fun BodyResolveComponents.mapArguments( name = function.valueParameters.last().name } argumentsInParenthesis = argumentsInParenthesis.dropLast(1) + listOf(namedV) + oldToNewArgumentMap[v] = namedV } } @@ -92,7 +95,7 @@ fun BodyResolveComponents.mapArguments( } processor.processDefaultsAndRunChecks() - return ArgumentMapping(processor.result, processor.diagnostics ?: emptyList()) + return ArgumentMapping(processor.result, oldToNewArgumentMap, processor.diagnostics ?: emptyList()) } private class FirCallArgumentsProcessor( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index c184071e083..6cd0c402238 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -172,6 +172,7 @@ internal object MapArguments : ResolutionStage() { val mapping = context.bodyResolveComponents.mapArguments(callInfo.arguments, function, candidate.originScope) candidate.argumentMapping = mapping.toArgumentToParameterMapping() candidate.numDefaults = mapping.numDefaults() + candidate.oldToNewArgumentMapping = mapping.oldToNewArgumentMap mapping.diagnostics.forEach(sink::reportDiagnostic) sink.yieldIfNeed() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index f6e571c20e6..1090a5f4cc4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedCallableReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference @@ -165,6 +166,14 @@ class FirCallCompletionResultsWriterTransformer( val expectedArgumentsTypeMapping = runIf(!calleeReference.isError) { subCandidate.createArgumentsMapping() } result.argumentList.transformArguments(this, expectedArgumentsTypeMapping) if (!calleeReference.isError) { + subCandidate.oldToNewArgumentMapping?.let { + result.replaceArgumentList(buildArgumentList { + source = result.argumentList.source + for (oldArgument in result.argumentList.arguments) { + arguments += it[oldArgument] ?: oldArgument + } + }) + } subCandidate.handleVarargs(result.argumentList) subCandidate.argumentMapping?.let { result.replaceArgumentList(buildResolvedArgumentList(it)) diff --git a/compiler/testData/codegen/box/increment/classVarargGetSet.kt b/compiler/testData/codegen/box/increment/classVarargGetSet.kt new file mode 100644 index 00000000000..c993d472cbb --- /dev/null +++ b/compiler/testData/codegen/box/increment/classVarargGetSet.kt @@ -0,0 +1,29 @@ +object A { + var x = 0 + var gets = 0 + var sets = 0 + + operator fun get(vararg va: Int): Int { + for (i in va) { + gets += i + } + return x + } + + operator fun set(vararg va: Int, value: Int) { + for (i in va) { + sets += i + } + x = value + } +} + +fun box(): String { + A.x = 0 + val xx = A[1, 2, 3]++ + if (xx != 0) return "Failed xx: $xx" + if (A.x != 1) return "Failed A.x: ${A.x}" + if (A.gets != 6) return "Failed A.gets: ${A.gets}" + if (A.sets != 6) return "Failed A.sets: ${A.sets}" + return "OK" +} diff --git a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt index 08857777990..cc17a127e45 100644 --- a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt +++ b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt @@ -28,8 +28,8 @@ fun test() { B[0] = 2.72 B[0] = true - D[0] = "" - D[0] = 2.72 + D[0] = "" + D[0] = 2.72 Z[0] = "" } diff --git a/compiler/testData/ir/irText/expressions/kt28456a.fir.txt b/compiler/testData/ir/irText/expressions/kt28456a.fir.txt index c6e6c96f163..48a288dc46b 100644 --- a/compiler/testData/ir/irText/expressions/kt28456a.fir.txt +++ b/compiler/testData/ir/irText/expressions/kt28456a.fir.txt @@ -26,8 +26,13 @@ FILE fqName: fileName:/kt28456a.kt FUN name:testSimpleAssignment visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:.A BLOCK_BODY - ERROR_CALL 'Unresolved reference: #' type=kotlin.Unit - CONST Int type=kotlin.Int value=1 - CONST Int type=kotlin.Int value=2 - CONST Int type=kotlin.Int value=3 - CONST Int type=kotlin.Int value=0 + BLOCK type=kotlin.Unit origin=ARGUMENTS_REORDERING_FOR_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.IntArray [val] + VARARG type=kotlin.IntArray varargElementType=kotlin.Int + CONST Int type=kotlin.Int value=1 + CONST Int type=kotlin.Int value=2 + CONST Int type=kotlin.Int value=3 + CALL 'public final fun set (vararg i: kotlin.Int, v: kotlin.Int): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=null + $receiver: GET_VAR 'a: .A declared in .testSimpleAssignment' type=.A origin=null + i: GET_VAR 'val tmp_0: kotlin.IntArray [val] declared in .testSimpleAssignment' type=kotlin.IntArray origin=null + v: CONST Int type=kotlin.Int value=0 diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d106e79bb1e..d1d593f8163 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -14406,6 +14406,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/increment/classNaryGetSet.kt"); } + @TestMetadata("classVarargGetSet.kt") + public void testClassVarargGetSet() throws Exception { + runTest("compiler/testData/codegen/box/increment/classVarargGetSet.kt"); + } + @TestMetadata("classWithGetSet.kt") public void testClassWithGetSet() throws Exception { runTest("compiler/testData/codegen/box/increment/classWithGetSet.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 89ccaa28486..21a09ddcf4f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -14406,6 +14406,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/increment/classNaryGetSet.kt"); } + @TestMetadata("classVarargGetSet.kt") + public void testClassVarargGetSet() throws Exception { + runTest("compiler/testData/codegen/box/increment/classVarargGetSet.kt"); + } + @TestMetadata("classWithGetSet.kt") public void testClassWithGetSet() throws Exception { runTest("compiler/testData/codegen/box/increment/classWithGetSet.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 044129db114..eb5d2117d72 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -13011,6 +13011,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/increment/classNaryGetSet.kt"); } + @TestMetadata("classVarargGetSet.kt") + public void testClassVarargGetSet() throws Exception { + runTest("compiler/testData/codegen/box/increment/classVarargGetSet.kt"); + } + @TestMetadata("classWithGetSet.kt") public void testClassWithGetSet() throws Exception { runTest("compiler/testData/codegen/box/increment/classWithGetSet.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 3872398bde7..34589f70705 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -11156,6 +11156,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/increment/classNaryGetSet.kt"); } + @TestMetadata("classVarargGetSet.kt") + public void testClassVarargGetSet() throws Exception { + runTest("compiler/testData/codegen/box/increment/classVarargGetSet.kt"); + } + @TestMetadata("classWithGetSet.kt") public void testClassWithGetSet() throws Exception { runTest("compiler/testData/codegen/box/increment/classWithGetSet.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 36a2de23c57..87e344a2cbe 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -11156,6 +11156,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/increment/classNaryGetSet.kt"); } + @TestMetadata("classVarargGetSet.kt") + public void testClassVarargGetSet() throws Exception { + runTest("compiler/testData/codegen/box/increment/classVarargGetSet.kt"); + } + @TestMetadata("classWithGetSet.kt") public void testClassWithGetSet() throws Exception { runTest("compiler/testData/codegen/box/increment/classWithGetSet.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 90c62d404a1..7f9159b3783 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -11221,6 +11221,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/increment/classNaryGetSet.kt"); } + @TestMetadata("classVarargGetSet.kt") + public void testClassVarargGetSet() throws Exception { + runTest("compiler/testData/codegen/box/increment/classVarargGetSet.kt"); + } + @TestMetadata("classWithGetSet.kt") public void testClassWithGetSet() throws Exception { runTest("compiler/testData/codegen/box/increment/classWithGetSet.kt");