[FIR] Fix arguments mapping for indexed set operator

Now processPositionArgument changes STATE as well as processNamedArgument

^KT-59386
This commit is contained in:
Ivan Kochurkin
2023-07-12 22:50:26 +02:00
committed by Space Team
parent 8f5294a508
commit 43c66ee0e5
4 changed files with 38 additions and 32 deletions
@@ -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
}
}
@@ -20,16 +20,23 @@ object Z {
}
}
object W {
operator fun set(vararg va: Int, value: Int) {
}
}
fun test() {
A[0] = ""
A[0] = <!ARGUMENT_TYPE_MISMATCH!>""<!>
A[0] = 2.72
B[0] = ""
B[0] = 2.72
B[0] = <!ARGUMENT_TYPE_MISMATCH!>""<!>
B[0] = <!ARGUMENT_TYPE_MISMATCH!>2.72<!>
B[0] = true
D[0] = ""
D[0] = <!ARGUMENT_TYPE_MISMATCH!>""<!>
D[0] = 2.72
Z[<!TOO_MANY_ARGUMENTS!>0<!>] = <!TOO_MANY_ARGUMENTS!>""<!>
W[0] = 1
}
@@ -20,6 +20,11 @@ object Z {
}
}
object W {
operator fun set(vararg va: Int, value: Int) {
}
}
fun test() {
A[0] = <!TYPE_MISMATCH!>""<!>
A[0] = 2.72
@@ -32,4 +37,6 @@ fun test() {
D[0] = 2.72
Z[<!TOO_MANY_ARGUMENTS!>0<!>] = <!TOO_MANY_ARGUMENTS!>""<!>
W[0] = 1
}
@@ -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
}