From 43c66ee0e51c42c6590e759aae866ce7c3eebbd0 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Wed, 12 Jul 2023 22:50:26 +0200 Subject: [PATCH] [FIR] Fix arguments mapping for indexed set operator Now processPositionArgument changes STATE as well as processNamedArgument ^KT-59386 --- .../calls/FirArgumentsToParametersMapper.kt | 39 ++++++------------- .../checkArguments/arrayAccessSet.fir.kt | 15 +++++-- .../tests/checkArguments/arrayAccessSet.kt | 7 ++++ .../tests/checkArguments/arrayAccessSet.txt | 9 +++++ 4 files changed, 38 insertions(+), 32 deletions(-) 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 1d3b393e209..47a08304d42 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 @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.utils.isOperator import org.jetbrains.kotlin.fir.expressions.* -import org.jetbrains.kotlin.fir.expressions.builder.buildNamedArgumentExpression import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.defaultParameterResolver @@ -95,22 +94,6 @@ fun BodyResolveComponents.mapArguments( && function.name == OperatorNameConventions.SET && function.origin !is FirDeclarationOrigin.DynamicScope - if (isIndexedSetOperator && - function.valueParameters.any { it.defaultValue != null || it.isVararg } - ) { - val v = nonLambdaArguments.last() - if (v !is FirNamedArgumentExpression) { - val namedV = buildNamedArgumentExpression { - source = v.source - expression = v - isSpread = false - name = function.valueParameters.last().name - } - nonLambdaArguments.removeAt(nonLambdaArguments.size - 1) - nonLambdaArguments.add(namedV) - } - } - val processor = FirCallArgumentsProcessor(session, function, this, originScope, isIndexedSetOperator) processor.processNonLambdaArguments(nonLambdaArguments) if (externalArgument != null) { @@ -172,15 +155,16 @@ private class FirCallArgumentsProcessor( when { // process position argument argument !is FirNamedArgumentExpression -> { - if (processPositionArgument(argument, isLastArgument)) { - state = State.VARARG_POSITION + if (state == State.VARARG_POSITION && isIndexedSetOperator && isLastArgument) { + // The last argument of an indexed set operator should be reserved for the last argument (the assigned value). + // That's why if vararg presented, they should be completed + completeVarargPositionArguments() } + processPositionArgument(argument, isLastArgument) } // process named argument function.origin == FirDeclarationOrigin.DynamicScope -> { - if (processPositionArgument(argument.expression, isLastArgument)) { - state = State.VARARG_POSITION - } + processPositionArgument(argument.expression, isLastArgument) } else -> { if (state == State.VARARG_POSITION) { @@ -191,11 +175,10 @@ private class FirCallArgumentsProcessor( } } - // return true, if it was mapped to vararg parameter - private fun processPositionArgument(argument: FirExpression, isLastArgument: Boolean): Boolean { + private fun processPositionArgument(argument: FirExpression, isLastArgument: Boolean) { if (state == State.NAMED_ONLY_ARGUMENTS) { addDiagnostic(MixingNamedAndPositionArguments(argument)) - return false + return } // The last parameter of an indexed set operator should be reserved for the last argument (the assigned value). @@ -219,19 +202,19 @@ private class FirCallArgumentsProcessor( val parameter = parameters.getOrNull(assignedParameterIndex) if (parameter == null) { addDiagnostic(TooManyArguments(argument, function)) - return false + return } return if (!parameter.isVararg) { currentPositionedParameterIndex++ result[parameter] = ResolvedCallArgument.SimpleArgument(argument) - false + state = State.POSITION_ARGUMENTS } // all position arguments will be mapped to current vararg parameter else { addVarargArgument(argument) - true + state = State.VARARG_POSITION } } diff --git a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt index 085af99f3d6..0100e71ee3a 100644 --- a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt +++ b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt @@ -20,16 +20,23 @@ object Z { } } +object W { + operator fun set(vararg va: Int, value: Int) { + } +} + fun test() { - A[0] = "" + A[0] = "" A[0] = 2.72 - B[0] = "" - B[0] = 2.72 + B[0] = "" + B[0] = 2.72 B[0] = true - D[0] = "" + D[0] = "" D[0] = 2.72 Z[0] = "" + + W[0] = 1 } diff --git a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.kt b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.kt index 65a40b9056e..a9421982f62 100644 --- a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.kt +++ b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.kt @@ -20,6 +20,11 @@ object Z { } } +object W { + operator fun set(vararg va: Int, value: Int) { + } +} + fun test() { A[0] = "" A[0] = 2.72 @@ -32,4 +37,6 @@ fun test() { D[0] = 2.72 Z[0] = "" + + W[0] = 1 } diff --git a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.txt b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.txt index 8d28e058ec6..c4a25c65639 100644 --- a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.txt +++ b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.txt @@ -26,6 +26,14 @@ public object D { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +public object W { + private constructor W() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final operator fun set(/*0*/ vararg va: kotlin.Int /*kotlin.IntArray*/, /*1*/ value: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + public object Z { private constructor Z() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean @@ -33,3 +41,4 @@ public object Z { public final operator fun set(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +