[FIR] Keep vararg argument order in resolved calls (KT-17691).

This commit is contained in:
Mark Punzalan
2020-09-24 13:43:18 -07:00
committed by teamcityserver
parent f6ce2d893c
commit eb631bc429
14 changed files with 265 additions and 14 deletions
@@ -13016,6 +13016,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/increment/classVarargGetSet.kt");
}
@TestMetadata("classVarargGetSetEvaluationOrder.kt")
public void testClassVarargGetSetEvaluationOrder() throws Exception {
runTest("compiler/testData/codegen/box/increment/classVarargGetSetEvaluationOrder.kt");
}
@TestMetadata("classWithGetSet.kt")
public void testClassWithGetSet() throws Exception {
runTest("compiler/testData/codegen/box/increment/classWithGetSet.kt");
@@ -17861,6 +17866,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
public void testVarargs() throws Exception {
runTest("compiler/testData/codegen/box/mixedNamedPosition/varargs.kt");
}
@TestMetadata("varargsEvaluationOrder.kt")
public void testVarargsEvaluationOrder() throws Exception {
runTest("compiler/testData/codegen/box/mixedNamedPosition/varargsEvaluationOrder.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/multiDecl")
@@ -31536,6 +31546,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/vararg/emptyVarargOfBoxedPrimitiveType.kt");
}
@TestMetadata("evaluationOrder.kt")
public void testEvaluationOrder() throws Exception {
runTest("compiler/testData/codegen/box/vararg/evaluationOrder.kt");
}
@TestMetadata("kt1978.kt")
public void testKt1978() throws Exception {
runTest("compiler/testData/codegen/box/vararg/kt1978.kt");
@@ -29,6 +29,8 @@ data class ArgumentMapping(
// fun foo(a: Int, b: Int) {}
// foo(b = bar(), a = qux())
// parameterToCallArgumentMap.values() should be [ 'bar()', 'foo()' ]
// TODO: Consider changing this (and other similar declarations like Candidate.argumentMapping) to LinkedHashMap to signify that
// order is important. Right now we're assuming that mutableMapOf() will always return a LinkedHashMap.
val parameterToCallArgumentMap: Map<FirValueParameter, ResolvedCallArgument>,
val oldToNewArgumentMap: Map<FirExpression, FirExpression>,
val diagnostics: List<ResolutionDiagnostic>
@@ -40,10 +40,12 @@ internal fun remapArgumentsWithVararg(
argumentList: FirArgumentList,
argumentMapping: Map<FirExpression, FirValueParameter>
): Map<FirExpression, FirValueParameter> {
// Create a FirVarargArgumentExpression for the vararg arguments
// Create a FirVarargArgumentExpression for the vararg arguments.
// The order of arguments in the mapping must be preserved for FIR2IR, hence we have to find where the vararg arguments end.
// FIR2IR uses the mapping order to determine if arguments need to be reordered.
val varargParameterTypeRef = varargParameter.returnTypeRef
val varargElementType = varargArrayType.arrayElementType()
var firstIndex = argumentList.arguments.size
var indexAfterVarargs = argumentList.arguments.size
val newArgumentMapping = mutableMapOf<FirExpression, FirValueParameter>()
val varargArgument = buildVarargArgumentsExpression {
this.varargElementType = varargParameterTypeRef.withReplacedConeType(varargElementType)
@@ -51,14 +53,26 @@ internal fun remapArgumentsWithVararg(
for ((i, arg) in argumentList.arguments.withIndex()) {
val valueParameter = argumentMapping[arg] ?: continue
if (valueParameter.isVararg) {
firstIndex = min(firstIndex, i)
// `arg` is a vararg argument.
arguments += arg
} else {
} else if (arguments.isEmpty()) {
// `arg` is BEFORE the vararg arguments.
newArgumentMapping[arg] = valueParameter
} else {
// `arg` is AFTER the vararg arguments.
indexAfterVarargs = i
break
}
}
}
newArgumentMapping[varargArgument] = varargParameter
// Add mapping for arguments after the vararg arguments, if any.
for (i in indexAfterVarargs until argumentList.arguments.size) {
val arg = argumentList.arguments[i]
val valueParameter = argumentMapping[arg] ?: continue
newArgumentMapping[arg] = valueParameter
}
return newArgumentMapping
}