[FIR] Fix arguments mapping for indexed set operator
Now processPositionArgument changes STATE as well as processNamedArgument ^KT-59386
This commit is contained in:
committed by
Space Team
parent
8f5294a508
commit
43c66ee0e5
+11
-28
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user