JVM: expect a continuation parameter in default suspend references

This commit is contained in:
pyos
2021-05-17 13:06:28 +02:00
committed by max-kammerer
parent 7eedcf75f9
commit 21f2b3fa2b
3 changed files with 28 additions and 12 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getMethodAsmFlags
@@ -352,13 +353,23 @@ class PsiDefaultLambda(
get() = invokeMethodDescriptor.returnType
override fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method {
invokeMethodDescriptor = parameterDescriptor.type.memberScope
val substitutedDescriptor = parameterDescriptor.type.memberScope
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
.single().let {
// Property references only have an erased `get` method, while function references and lambdas
// have a non-erased `invoke` with an erased synthetic bridge, and we want to inline the former.
if (isPropertyReference) it.original else it
}
.single()
invokeMethodDescriptor = when {
// Property references: `(A) -> B` => `get(Any?): Any?`
isPropertyReference -> substitutedDescriptor.original
// Suspend function references: `suspend (A) -> B` => `invoke(A, Continuation<B>): Any?`
// TODO: default suspend lambdas are currently uninlinable
parameterDescriptor.type.isSuspendFunctionType ->
getOrCreateJvmSuspendFunctionView(
substitutedDescriptor,
sourceCompiler.state.languageVersionSettings.isReleaseCoroutines(),
sourceCompiler.state.bindingContext
)
// Non-suspend function references and lambdas: `(A) -> B` => `invoke(A): B`
else -> substitutedDescriptor
}
return sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod
}
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
@@ -251,12 +252,19 @@ class IrDefaultLambda(
override fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method {
val context = (sourceCompiler as IrSourceCompilerForInline).codegen.context
typeArguments = (irValueParameter.type as IrSimpleType).arguments.let {
// Property references only have an erased `get` method, while function references and lambdas
// have a non-erased `invoke` with an erased synthetic bridge, and we want to inline the former.
if (isPropertyReference) {
// Property references: `(A) -> B` => `get(Any?): Any?`
List(it.size) { context.irBuiltIns.anyNType }
} else {
it.map { argument -> (argument as IrTypeProjection).type }
// Non-suspend function references and lambdas: `(A) -> B` => `invoke(A): B`
// Suspend function references: `suspend (A) -> B` => `invoke(A, Continuation<B>): Any?`
// TODO: default suspend lambdas are currently uninlinable
it.mapTo(mutableListOf()) { argument -> (argument as IrTypeProjection).type }.apply {
if (irValueParameter.type.isSuspendFunction()) {
set(size - 1, context.ir.symbols.continuationClass.typeWith(get(size - 1)))
add(context.irBuiltIns.anyNType)
}
}
}
}
val base = if (isPropertyReference) OperatorNameConventions.GET.asString() else OperatorNameConventions.INVOKE.asString()
@@ -1,9 +1,6 @@
// SKIP_INLINE_CHECK_IN: bar$default
// WITH_RUNTIME
// WITH_COROUTINES
// IGNORE_BACKEND: JVM, JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_IR, JVM_MULTI_MODULE_OLD_AGAINST_IR, JVM_MULTI_MODULE_IR_AGAINST_OLD
// FILE: 1.kt
package test