JVM_IR: Fix bug in suspend function with many default arguments.
This commit is contained in:
@@ -197,7 +197,7 @@ fun IrFunction.copyValueParametersInsertingContinuationFrom(from: IrFunction, in
|
||||
var additionalShift = 0
|
||||
from.valueParameters.forEach {
|
||||
// The continuation parameter goes before the default argument mask and handler.
|
||||
if (it.origin == IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION) {
|
||||
if (it.origin == IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION && additionalShift == 0) {
|
||||
insertContinuation()
|
||||
additionalShift = 1
|
||||
}
|
||||
|
||||
+11
-10
@@ -167,7 +167,7 @@ private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFuncti
|
||||
it.copyTypeParametersFrom(this)
|
||||
|
||||
// Copy the value parameters and insert the continuation parameter. The continuation parameter
|
||||
// goes before the default argument mask and handler for default argument stubs.
|
||||
// goes before the default argument mask(s) and handler for default argument stubs.
|
||||
// TODO: It would be nice if AddContinuationLowering could insert the continuation argument before default stub generation.
|
||||
// That would avoid the reshuffling both here and in createSuspendFunctionClassViewIfNeeded.
|
||||
var continuationValueParam: IrValueParameter? = null
|
||||
@@ -203,9 +203,9 @@ internal fun IrCall.createSuspendFunctionCallViewIfNeeded(
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
it.dispatchReceiver = dispatchReceiver
|
||||
it.extensionReceiver = extensionReceiver
|
||||
// Locate the caller continuation parameter. The continuation parameter is before default argument mask and handler params.
|
||||
val callerHasDefaultMask = caller.valueParameters.lastOrNull()?.origin == IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION
|
||||
val callerContinuationIndex = caller.valueParameters.size - 1 - (if (callerHasDefaultMask) 2 else 0)
|
||||
// Locate the caller continuation parameter. The continuation parameter is before default argument mask(s) and handler params.
|
||||
val callerNumberOfMasks = caller.valueParameters.count { it.origin == IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION }
|
||||
val callerContinuationIndex = caller.valueParameters.size - 1 - (if (callerNumberOfMasks != 0) callerNumberOfMasks + 1 else 0)
|
||||
val continuationParameter =
|
||||
when {
|
||||
caller.isInvokeSuspendOfLambda() || caller.isInvokeSuspendOfContinuation() ||
|
||||
@@ -215,16 +215,17 @@ internal fun IrCall.createSuspendFunctionCallViewIfNeeded(
|
||||
else -> IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, caller.valueParameters[callerContinuationIndex].symbol)
|
||||
}
|
||||
// If the suspend function view that we are calling has default parameters, we need to make sure to pass the
|
||||
// continuation before the default parameter mask and handler.
|
||||
val hasDefaultMask = view.valueParameters.last().origin == IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION
|
||||
val continuationIndex = valueArgumentsCount - (if (hasDefaultMask) 2 else 0)
|
||||
// continuation before the default parameter mask(s) and handler.
|
||||
val numberOfMasks = view.valueParameters.count { it.origin == IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION }
|
||||
val continuationIndex = valueArgumentsCount - (if (numberOfMasks != 0) numberOfMasks + 1 else 0)
|
||||
for (i in 0 until continuationIndex) {
|
||||
it.putValueArgument(i, getValueArgument(i))
|
||||
}
|
||||
it.putValueArgument(continuationIndex, continuationParameter)
|
||||
if (hasDefaultMask) {
|
||||
it.putValueArgument(valueArgumentsCount - 1, getValueArgument(continuationIndex))
|
||||
it.putValueArgument(valueArgumentsCount, getValueArgument(continuationIndex + 1))
|
||||
if (numberOfMasks != 0) {
|
||||
for (i in 0 until numberOfMasks + 1) {
|
||||
it.putValueArgument(valueArgumentsCount + i - 1, getValueArgument(continuationIndex + i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,43 @@ fun ordinary() = "OK"
|
||||
|
||||
suspend fun withDefault(s: String = "OK") = s
|
||||
|
||||
suspend fun withManyDefault(
|
||||
s0: String = "NOT OK 0",
|
||||
s1: String = "NOT OK 1",
|
||||
s2: String = "NOT OK 2",
|
||||
s3: String = "NOT OK 3",
|
||||
s4: String = "NOT OK 4",
|
||||
s5: String = "NOT OK 5",
|
||||
s6: String = "NOT OK 6",
|
||||
s7: String = "NOT OK 7",
|
||||
s8: String = "NOT OK 8",
|
||||
s9: String = "NOT OK 9",
|
||||
s10: String = "NOT OK 10",
|
||||
s11: String = "NOT OK 11",
|
||||
s12: String = "NOT OK 12",
|
||||
s13: String = "NOT OK 13",
|
||||
s14: String = "NOT OK 14",
|
||||
s15: String = "NOT OK 15",
|
||||
s16: String = "NOT OK 16",
|
||||
s17: String = "NOT OK 17",
|
||||
s18: String = "NOT OK 18",
|
||||
s19: String = "NOT OK 19",
|
||||
s20: String = "NOT OK 20",
|
||||
s21: String = "NOT OK 21",
|
||||
s22: String = "NOT OK 22",
|
||||
s23: String = "NOT OK 23",
|
||||
s24: String = "NOT OK 24",
|
||||
s25: String = "NOT OK 25",
|
||||
s26: String = "NOT OK 26",
|
||||
s27: String = "NOT OK 27",
|
||||
s28: String = "NOT OK 28",
|
||||
s29: String = "NOT OK 29",
|
||||
s30: String = "NOT OK 30",
|
||||
s31: String = "NOT OK 31",
|
||||
s32: String = "NOT OK 32",
|
||||
ok: String = "OK"
|
||||
) = ok
|
||||
|
||||
var log = ""
|
||||
|
||||
var proceed = {}
|
||||
@@ -64,6 +101,10 @@ fun box(): String {
|
||||
builder {
|
||||
res = ::withDefault.callSuspendBy(emptyMap()) as String?
|
||||
}
|
||||
if (res != "OK") return res ?: "FAIL 5"
|
||||
builder {
|
||||
res = ::withManyDefault.callSuspendBy(emptyMap()) as String?
|
||||
}
|
||||
builder {
|
||||
::suspending.callSuspendBy(emptyMap())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user