JVM IR: Handle suspend interface default methods with generic types (KT-45166)
This commit is contained in:
committed by
Alexander Udalov
parent
7d62f0b5aa
commit
7a9ff15d73
+6
@@ -9429,6 +9429,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/bridges"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("interfaceGenericDefault.kt")
|
||||
public void testInterfaceGenericDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceGenericDefault.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("interfaceSpecialization.kt")
|
||||
public void testInterfaceSpecialization() throws Exception {
|
||||
|
||||
+10
-11
@@ -79,8 +79,8 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
|
||||
val transformed = super.visitCall(expression) as IrCall
|
||||
return transformed.retargetToSuspendView(context, functionStack.peek() ?: return transformed) {
|
||||
IrCallImpl.fromSymbolOwner(
|
||||
startOffset, endOffset, type, it,
|
||||
origin = origin, superQualifierSymbol = superQualifierSymbol
|
||||
startOffset, endOffset, type, it,
|
||||
origin = origin, superQualifierSymbol = superQualifierSymbol
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -261,11 +261,11 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun transformToView(function: IrSimpleFunction): List<IrFunction>? {
|
||||
private fun transformToView(function: IrSimpleFunction): List<IrFunction> {
|
||||
val flag = MutableFlag(false)
|
||||
function.accept(this, flag)
|
||||
|
||||
val view = function.suspendFunctionViewOrStub(context) as IrSimpleFunction
|
||||
val view = function.suspendFunctionViewOrStub(context)
|
||||
val continuationParameter = view.continuationParameter()
|
||||
val parameterMap = function.explicitParameters.zip(view.explicitParameters.filter { it != continuationParameter }).toMap()
|
||||
view.body = function.moveBodyTo(view, parameterMap)
|
||||
@@ -334,7 +334,7 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
|
||||
|
||||
// Transform `suspend fun foo(params): RetType` into `fun foo(params, $completion: Continuation<RetType>): Any?`
|
||||
// the result is called 'view', just to be consistent with old backend.
|
||||
private fun IrSimpleFunction.suspendFunctionViewOrStub(context: JvmBackendContext): IrFunction {
|
||||
private fun IrSimpleFunction.suspendFunctionViewOrStub(context: JvmBackendContext): IrSimpleFunction {
|
||||
if (!isSuspend) return this
|
||||
return context.suspendFunctionOriginalToView.getOrPut(suspendFunctionOriginal()) { createSuspendFunctionStub(context) }
|
||||
}
|
||||
@@ -377,10 +377,7 @@ private fun IrSimpleFunction.createSuspendFunctionStub(context: JvmBackendContex
|
||||
val substitutionMap = makeTypeParameterSubstitutionMap(this, function)
|
||||
function.copyReceiverParametersFrom(this, substitutionMap)
|
||||
|
||||
if (origin != JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE) {
|
||||
function.overriddenSymbols +=
|
||||
overriddenSymbols.map { it.owner.suspendFunctionViewOrStub(context).symbol as IrSimpleFunctionSymbol }
|
||||
}
|
||||
function.overriddenSymbols += overriddenSymbols.map { it.owner.suspendFunctionViewOrStub(context).symbol }
|
||||
|
||||
// The continuation parameter 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.
|
||||
@@ -390,7 +387,9 @@ private fun IrSimpleFunction.createSuspendFunctionStub(context: JvmBackendContex
|
||||
it.copyTo(function, index = it.index, type = it.type.substitute(substitutionMap))
|
||||
}
|
||||
function.addValueParameter(
|
||||
SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME, continuationType(context).substitute(substitutionMap), JvmLoweredDeclarationOrigin.CONTINUATION_CLASS
|
||||
SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME,
|
||||
continuationType(context).substitute(substitutionMap),
|
||||
JvmLoweredDeclarationOrigin.CONTINUATION_CLASS
|
||||
)
|
||||
function.valueParameters += valueParameters.drop(index).map {
|
||||
it.copyTo(function, index = it.index + 1, type = it.type.substitute(substitutionMap))
|
||||
@@ -427,7 +426,7 @@ private fun <T : IrMemberAccessExpression<IrFunctionSymbol>> T.retargetToSuspend
|
||||
|
||||
// While the new callee technically returns `<original type> | COROUTINE_SUSPENDED`, the latter case is handled
|
||||
// by a method visitor so at an IR overview we don't need to consider it.
|
||||
return copyWithTargetSymbol(view.symbol as IrSimpleFunctionSymbol).also {
|
||||
return copyWithTargetSymbol(view.symbol).also {
|
||||
it.copyAttributes(this)
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
it.dispatchReceiver = dispatchReceiver
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Corresponds to KT-45166, KT-45320, KT-45490, and KT-45954.
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
interface I<T> {
|
||||
suspend fun f(x: T): String = "OK"
|
||||
}
|
||||
|
||||
class C : I<String>
|
||||
|
||||
fun box(): String {
|
||||
var result = "Fail"
|
||||
suspend {
|
||||
result = (C() as I<String>).f("Fail")
|
||||
}.startCoroutine(EmptyContinuation)
|
||||
return result
|
||||
}
|
||||
+6
@@ -9429,6 +9429,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/bridges"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("interfaceGenericDefault.kt")
|
||||
public void testInterfaceGenericDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceGenericDefault.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("interfaceSpecialization.kt")
|
||||
public void testInterfaceSpecialization() throws Exception {
|
||||
|
||||
+6
@@ -9429,6 +9429,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/bridges"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("interfaceGenericDefault.kt")
|
||||
public void testInterfaceGenericDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceGenericDefault.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("interfaceSpecialization.kt")
|
||||
public void testInterfaceSpecialization() throws Exception {
|
||||
|
||||
+5
@@ -7386,6 +7386,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/bridges"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceGenericDefault.kt")
|
||||
public void testInterfaceGenericDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceGenericDefault.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceSpecialization.kt")
|
||||
public void testInterfaceSpecialization() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceSpecialization.kt");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+5
@@ -6605,6 +6605,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/bridges"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceGenericDefault.kt")
|
||||
public void testInterfaceGenericDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceGenericDefault.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceSpecialization.kt")
|
||||
public void testInterfaceSpecialization() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceSpecialization.kt");
|
||||
|
||||
Generated
+5
@@ -6026,6 +6026,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/bridges"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceGenericDefault.kt")
|
||||
public void testInterfaceGenericDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceGenericDefault.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceSpecialization.kt")
|
||||
public void testInterfaceSpecialization() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceSpecialization.kt");
|
||||
|
||||
Generated
+5
@@ -6026,6 +6026,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/bridges"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceGenericDefault.kt")
|
||||
public void testInterfaceGenericDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceGenericDefault.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceSpecialization.kt")
|
||||
public void testInterfaceSpecialization() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/bridges/interfaceSpecialization.kt");
|
||||
|
||||
Reference in New Issue
Block a user