[FIR] add support for varargs in delegated constructor calls

Also add support for spread operators as named arguments.
This commit is contained in:
Juan Chen
2020-05-12 17:53:16 -07:00
committed by Dmitriy Novozhilov
parent 3652ac9354
commit 858731cac8
8 changed files with 33 additions and 34 deletions
@@ -258,7 +258,9 @@ class Fir2IrVisitor(
varargArgumentsExpression.varargElementType.toIrType(),
varargArgumentsExpression.arguments.map { arg ->
convertToIrExpression(arg).run {
if (arg is FirSpreadArgumentExpression) IrSpreadElementImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this)
if (arg is FirSpreadArgumentExpression || arg is FirNamedArgumentExpression && arg.isSpread) {
IrSpreadElementImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this)
}
else this
}
})
@@ -133,34 +133,8 @@ class FirCallCompletionResultsWriterTransformer(
}
else -> {
resultType = typeRef.substituteTypeRef(subCandidate)
val argumentMapping = subCandidate.argumentMapping
val varargParameter = argumentMapping?.values?.firstOrNull { it.isVararg }
result.argumentList.transformArguments(this, subCandidate.createArgumentsMapping())
with(result.argumentList) call@{
if (varargParameter != null) {
// Create a FirVarargArgumentExpression for the vararg arguments
val varargParameterTypeRef = varargParameter.returnTypeRef
val resolvedArrayType = varargParameterTypeRef.substitute(subCandidate)
val resolvedElementType = resolvedArrayType.arrayElementType(session)
var firstIndex = this@call.arguments.size
val newArgumentMapping = mutableMapOf<FirExpression, FirValueParameter>()
val varargArgument = buildVarargArgumentsExpression {
varargElementType = varargParameterTypeRef.withReplacedConeType(resolvedElementType)
this.typeRef = varargParameterTypeRef.withReplacedConeType(resolvedArrayType)
for ((i, arg) in this@call.arguments.withIndex()) {
val valueParameter = argumentMapping[arg] ?: continue
if (valueParameter.isVararg) {
firstIndex = min(firstIndex, i)
arguments += arg
} else {
newArgumentMapping[arg] = valueParameter
}
}
}
newArgumentMapping[varargArgument] = varargParameter
subCandidate.argumentMapping = newArgumentMapping
}
}
subCandidate.handleVarargs(result.argumentList)
subCandidate.argumentMapping?.let {
result.replaceArgumentList(buildResolvedArgumentList(it))
}
@@ -180,6 +154,34 @@ class FirCallCompletionResultsWriterTransformer(
return result.compose()
}
private fun Candidate.handleVarargs(argumentList: FirArgumentList) {
val argumentMapping = this.argumentMapping
val varargParameter = argumentMapping?.values?.firstOrNull { it.isVararg }
if (varargParameter != null) {
// Create a FirVarargArgumentExpression for the vararg arguments
val varargParameterTypeRef = varargParameter.returnTypeRef
val resolvedArrayType = varargParameterTypeRef.substitute(this)
val resolvedElementType = resolvedArrayType.arrayElementType(session)
var firstIndex = argumentList.arguments.size
val newArgumentMapping = mutableMapOf<FirExpression, FirValueParameter>()
val varargArgument = buildVarargArgumentsExpression {
varargElementType = varargParameterTypeRef.withReplacedConeType(resolvedElementType)
this.typeRef = varargParameterTypeRef.withReplacedConeType(resolvedArrayType)
for ((i, arg) in argumentList.arguments.withIndex()) {
val valueParameter = argumentMapping[arg] ?: continue
if (valueParameter.isVararg) {
firstIndex = min(firstIndex, i)
arguments += arg
} else {
newArgumentMapping[arg] = valueParameter
}
}
}
newArgumentMapping[varargArgument] = varargParameter
this.argumentMapping = newArgumentMapping
}
}
private fun <D : FirExpression> D.replaceTypeRefWithSubstituted(
calleeReference: FirNamedReferenceWithCandidate,
typeRef: FirResolvedTypeRef,
@@ -291,6 +293,7 @@ class FirCallCompletionResultsWriterTransformer(
val subCandidate = calleeReference.candidate
delegatedConstructorCall.argumentList.transformArguments(this, calleeReference.candidate.createArgumentsMapping())
subCandidate.handleVarargs(delegatedConstructorCall.argumentList)
subCandidate.argumentMapping?.let {
delegatedConstructorCall.replaceArgumentList(buildResolvedArgumentList(it))
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class SomeClass(val some: Double, val other: Int, vararg val args: String) {
fun result() = args[1]
}
@@ -1,5 +1,4 @@
// !LANGUAGE: +NewInference +MixedNamedArgumentsInTheirOwnPosition
// IGNORE_BACKEND_FIR: JVM_IR
fun foo1(
vararg p1: Int,
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// See also KT-6299
public open class Outer private constructor(val s: String, vararg i: Int) {
class Inner: Outer("xyz")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun join(x: Array<out String>): String {
var result = ""
for (i in x) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun booleanVararg(vararg xs: Boolean) {
if (xs.size != 1 && xs[0] != true) throw AssertionError()
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
if (test1() != "") return "fail 1"
if (test1(1) != "1") return "fail 2"