JVM_IR indy-SAM conversions: use old scheme for suspend funs
KT-44278 KT-26060 KT-42621
This commit is contained in:
+6
@@ -18481,6 +18481,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("suspendFunInterface.kt")
|
||||
public void testSuspendFunInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/suspendFunInterface.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
@@ -389,3 +389,9 @@ private fun JvmBackendContext.makeRawTypeAnnotation() =
|
||||
|
||||
fun IrClass.rawType(context: JvmBackendContext): IrType =
|
||||
defaultType.addAnnotations(listOf(context.makeRawTypeAnnotation()))
|
||||
|
||||
fun IrType.getSingleAbstractMethod(): IrSimpleFunction? =
|
||||
getClass()?.getSingleAbstractMethod()
|
||||
|
||||
fun IrClass.getSingleAbstractMethod(): IrSimpleFunction? =
|
||||
functions.singleOrNull { it.modality == Modality.ABSTRACT }
|
||||
+15
-11
@@ -105,14 +105,15 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
}
|
||||
reference.transformChildrenVoid()
|
||||
|
||||
return if (shouldUseIndySamConversions && canUseIndySamConversion(reference)) {
|
||||
val samSuperType = expression.typeOperand
|
||||
return if (shouldUseIndySamConversions && canUseIndySamConversion(reference, samSuperType)) {
|
||||
wrapSamConversionArgumentWithIndySamConversion(expression)
|
||||
} else {
|
||||
FunctionReferenceBuilder(reference, expression.typeOperand).build()
|
||||
FunctionReferenceBuilder(reference, samSuperType).build()
|
||||
}
|
||||
}
|
||||
|
||||
private fun canUseIndySamConversion(reference: IrFunctionReference): Boolean {
|
||||
private fun canUseIndySamConversion(reference: IrFunctionReference, samSuperType: IrType): Boolean {
|
||||
// Can't use indy for regular function references by default (because of 'equals').
|
||||
// TODO special mode that would generate indy everywhere?
|
||||
if (reference.origin != IrStatementOrigin.LAMBDA)
|
||||
@@ -122,6 +123,10 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
if (context.irIntrinsics.getIntrinsic(reference.symbol) != null)
|
||||
return false
|
||||
|
||||
// Can't use JDK LambdaMetafactory for fun interface with suspend fun
|
||||
if (samSuperType.getSingleAbstractMethod()?.isSuspend == true)
|
||||
return false
|
||||
|
||||
// Can't use JDK LambdaMetafactory if lambda signature contains an inline class mapped to a non-null reference type.
|
||||
val target = reference.symbol.owner
|
||||
if (target.extensionReceiverParameter?.run { type.isProhibitedTypeForIndySamConversion() } == true ||
|
||||
@@ -201,10 +206,8 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
if (irLambda.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA)
|
||||
throw AssertionError("Can't patch a signature of a non-lambda: ${irLambda.render()}")
|
||||
|
||||
val samClass = samType.classOrNull?.owner
|
||||
?: throw AssertionError("SAM type should be a class type: '${samType.render()}'")
|
||||
val samMethod = samClass.functions.singleOrNull { it.modality == Modality.ABSTRACT }
|
||||
?: throw AssertionError("SAM method not found:\n${samClass.dump()}")
|
||||
val samMethod = samType.getSingleAbstractMethod()
|
||||
?: throw AssertionError("SAM method not found:\n${samType.render()}")
|
||||
|
||||
val samMethodParameters = collectValueParameters(samMethod)
|
||||
val irLambdaParameters = collectValueParameters(irLambda)
|
||||
@@ -265,7 +268,8 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
else
|
||||
context.ir.symbols.getJvmFunctionClass(argumentTypes.size)
|
||||
private val superMethod =
|
||||
functionSuperClass.functions.single { it.owner.modality == Modality.ABSTRACT }
|
||||
functionSuperClass.owner.getSingleAbstractMethod()
|
||||
?: throw AssertionError("Not a SAM class: ${functionSuperClass.owner.render()}")
|
||||
|
||||
private val useOptimizedSuperClass =
|
||||
context.state.generateOptimizedCallableReferenceSuperClasses
|
||||
@@ -546,12 +550,12 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
// For functions with inline class return type we need to mangle the invoke method.
|
||||
// Otherwise, bridge lowering may fail to generate bridges for inline class types erasing to Any.
|
||||
val suffix = InlineClassAbi.hashReturnSuffix(callee)
|
||||
Name.identifier("${superMethod.owner.name.asString()}-${suffix}")
|
||||
} else superMethod.owner.name
|
||||
Name.identifier("${superMethod.name.asString()}-${suffix}")
|
||||
} else superMethod.name
|
||||
returnType = callee.returnType
|
||||
isSuspend = callee.isSuspend
|
||||
}.apply {
|
||||
overriddenSymbols += superMethod
|
||||
overriddenSymbols += superMethod.symbol
|
||||
dispatchReceiverParameter = buildReceiverParameter(
|
||||
this,
|
||||
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
||||
|
||||
+2
-5
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.fileParent
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.getSingleAbstractMethod
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.functions
|
||||
import org.jetbrains.kotlin.ir.util.isInlined
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
@@ -178,9 +177,7 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
|
||||
|
||||
val samType = call.getTypeArgument(0) as? IrSimpleType
|
||||
?: fail("'samType' is expected to be a simple type")
|
||||
val samClassSymbol = samType.classOrNull
|
||||
?: fail("'samType' is expected to be a class type: '${samType.render()}'")
|
||||
val samMethod = samClassSymbol.owner.functions.singleOrNull { it.modality == Modality.ABSTRACT }
|
||||
val samMethod = samType.getSingleAbstractMethod()
|
||||
?: fail("'${samType.render()}' is not a SAM-type")
|
||||
|
||||
val irFunRef = call.getValueArgument(0) as? IrFunctionReference
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.transformIfNeeded
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
|
||||
abstract class IrFunction :
|
||||
IrDeclarationBase(),
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// !LANGUAGE: +SuspendFunctionsInFunInterfaces +JvmIrEnabledByDefault
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import kotlin.coroutines.*
|
||||
|
||||
var c: Continuation<Unit>? = null
|
||||
|
||||
suspend fun suspendMe() = suspendCoroutine<Unit> { continuation ->
|
||||
c = continuation
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context = EmptyCoroutineContext
|
||||
override fun resumeWith(result: Result<Unit>) {
|
||||
result.getOrThrow()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun interface SuspendFoo {
|
||||
suspend fun foo()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var test = ""
|
||||
val lambda = SuspendFoo {
|
||||
suspendMe()
|
||||
test += "O"
|
||||
suspendMe()
|
||||
test += "K"
|
||||
}
|
||||
builder {
|
||||
lambda.foo()
|
||||
}
|
||||
c?.resume(Unit)
|
||||
c?.resume(Unit)
|
||||
return test
|
||||
}
|
||||
+6
@@ -18481,6 +18481,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("suspendFunInterface.kt")
|
||||
public void testSuspendFunInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/suspendFunInterface.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+6
@@ -18481,6 +18481,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("suspendFunInterface.kt")
|
||||
public void testSuspendFunInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/suspendFunInterface.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+5
@@ -16203,6 +16203,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendFunInterface.kt")
|
||||
public void testSuspendFunInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/suspendFunInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user