JVM: expect a continuation parameter in default suspend references
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.inline
|
package org.jetbrains.kotlin.codegen.inline
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getMethodAsmFlags
|
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getMethodAsmFlags
|
||||||
@@ -352,13 +353,23 @@ class PsiDefaultLambda(
|
|||||||
get() = invokeMethodDescriptor.returnType
|
get() = invokeMethodDescriptor.returnType
|
||||||
|
|
||||||
override fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method {
|
override fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method {
|
||||||
invokeMethodDescriptor = parameterDescriptor.type.memberScope
|
val substitutedDescriptor = parameterDescriptor.type.memberScope
|
||||||
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
|
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
|
||||||
.single().let {
|
.single()
|
||||||
// Property references only have an erased `get` method, while function references and lambdas
|
invokeMethodDescriptor = when {
|
||||||
// have a non-erased `invoke` with an erased synthetic bridge, and we want to inline the former.
|
// Property references: `(A) -> B` => `get(Any?): Any?`
|
||||||
if (isPropertyReference) it.original else it
|
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
|
return sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-3
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||||
|
import org.jetbrains.kotlin.ir.types.typeWith
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
@@ -251,12 +252,19 @@ class IrDefaultLambda(
|
|||||||
override fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method {
|
override fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method {
|
||||||
val context = (sourceCompiler as IrSourceCompilerForInline).codegen.context
|
val context = (sourceCompiler as IrSourceCompilerForInline).codegen.context
|
||||||
typeArguments = (irValueParameter.type as IrSimpleType).arguments.let {
|
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) {
|
if (isPropertyReference) {
|
||||||
|
// Property references: `(A) -> B` => `get(Any?): Any?`
|
||||||
List(it.size) { context.irBuiltIns.anyNType }
|
List(it.size) { context.irBuiltIns.anyNType }
|
||||||
} else {
|
} 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()
|
val base = if (isPropertyReference) OperatorNameConventions.GET.asString() else OperatorNameConventions.INVOKE.asString()
|
||||||
|
|||||||
-3
@@ -1,9 +1,6 @@
|
|||||||
// SKIP_INLINE_CHECK_IN: bar$default
|
// SKIP_INLINE_CHECK_IN: bar$default
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// 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
|
// FILE: 1.kt
|
||||||
package test
|
package test
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user