JVM_IR: box inline class values returned by suspend inline lambdas
The call site inside the inline function expects them to return a boxed value, like FunctionN.invoke would. #KT-46915 Fixed
This commit is contained in:
+12
@@ -4981,12 +4981,24 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
|
||||
+10
-2
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
|
||||
import org.jetbrains.kotlin.codegen.IrExpressionLambda
|
||||
import org.jetbrains.kotlin.codegen.JvmKotlinType
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
@@ -215,11 +216,18 @@ class IrExpressionLambdaImpl(
|
||||
val isSuspend = parameter.isInlineParameter() && parameter.type.isSuspendFunctionTypeOrSubtype()
|
||||
capturedParamDesc(parameter.name.asString(), asmMethod.argumentTypes[startCapture + index], isSuspend)
|
||||
}
|
||||
// The parameter list should include the continuation if this is a suspend lambda. In the IR backend,
|
||||
// the lambda is suspend iff the inline function's parameter is marked suspend, so FunctionN.invoke call
|
||||
// inside the inline function already has a (real) continuation value as the last argument.
|
||||
val freeParameters = function.explicitParameters.let { it.take(startCapture) + it.drop(endCapture) }
|
||||
val freeAsmParameters = asmMethod.argumentTypes.let { it.take(startCapture) + it.drop(endCapture) }
|
||||
invokeMethod = Method(asmMethod.name, asmMethod.returnType, freeAsmParameters.toTypedArray())
|
||||
// The return type, on the other hand, should be the original type if this is a suspend lambda that returns
|
||||
// an unboxed inline class value so that the inliner will box it (FunctionN.invoke should return a boxed value).
|
||||
val unboxedReturnType = function.suspendFunctionOriginal().originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
|
||||
val unboxedAsmReturnType = unboxedReturnType?.let(codegen.typeMapper::mapType)
|
||||
invokeMethod = Method(asmMethod.name, unboxedAsmReturnType ?: asmMethod.returnType, freeAsmParameters.toTypedArray())
|
||||
invokeMethodParameters = freeParameters.map { it.type.toIrBasedKotlinType() }
|
||||
invokeMethodReturnType = function.returnType.toIrBasedKotlinType()
|
||||
invokeMethodReturnType = (unboxedReturnType ?: function.returnType).toIrBasedKotlinType()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// FILE: 1.kt
|
||||
inline fun <T, R> (suspend () -> T).map(crossinline transform: suspend (T) -> R): suspend () -> R =
|
||||
{ transform(this()) }
|
||||
|
||||
// FILE: 2.kt
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
inline class C(val value: Int)
|
||||
|
||||
fun box(): String {
|
||||
var result = 0
|
||||
suspend {
|
||||
result = suspend { C(1) as C? }.map { it }()?.value ?: 2
|
||||
}.startCoroutine(EmptyContinuation)
|
||||
return if (result == 1) "OK" else "fail: $result"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// FILE: 1.kt
|
||||
inline fun <T, R> (suspend () -> T).map(crossinline transform: suspend (T) -> R): suspend () -> R =
|
||||
{ transform(this()) }
|
||||
|
||||
// FILE: 2.kt
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
inline class C(val value: String)
|
||||
|
||||
fun box(): String {
|
||||
var result = "fail"
|
||||
suspend {
|
||||
result = suspend { C("OK") }.map { it }().value
|
||||
}.startCoroutine(EmptyContinuation)
|
||||
return result
|
||||
}
|
||||
+12
@@ -4981,12 +4981,24 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
|
||||
+12
@@ -4981,12 +4981,24 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
|
||||
+12
@@ -4981,12 +4981,24 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
|
||||
+12
@@ -4981,12 +4981,24 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
|
||||
+12
@@ -4981,12 +4981,24 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_IR_AGAINST_OLD, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
|
||||
+12
@@ -4981,12 +4981,24 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_OLD_AGAINST_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
|
||||
+10
@@ -3990,11 +3990,21 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||
}
|
||||
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedResume.kt");
|
||||
|
||||
Generated
+10
@@ -3990,11 +3990,21 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedResume.kt");
|
||||
|
||||
Generated
+10
@@ -3990,11 +3990,21 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/inlineClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("returnBoxedFromLambda.kt")
|
||||
public void testReturnBoxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnBoxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnboxedDirect.kt")
|
||||
public void testReturnUnboxedDirect() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedDirect.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnboxedFromLambda.kt")
|
||||
public void testReturnUnboxedFromLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedFromLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnUnboxedResume.kt")
|
||||
public void testReturnUnboxedResume() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/suspend/inlineClass/returnUnboxedResume.kt");
|
||||
|
||||
Reference in New Issue
Block a user