Box inline class returned from suspend lambda non-locally
All inline classes should be boxed coming in and out of lambdas, however, if the inline class was returned non-locally, it was not boxed. This change fixes the issue in Old JVM BE. #KT-41194 In progress
This commit is contained in:
@@ -1708,17 +1708,23 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
// This is inline lambda. Find inline-site and check, whether it is suspend functions returning unboxed inline class
|
// This is inline lambda. Find inline-site and check, whether it is suspend functions returning unboxed inline class
|
||||||
CodegenContext<?> inlineSiteContext = this.context.getFirstCrossInlineOrNonInlineContext();
|
CodegenContext<?> inlineSiteContext = this.context.getFirstCrossInlineOrNonInlineContext();
|
||||||
KotlinType originalInlineClass = null;
|
KotlinType originalInlineClass = null;
|
||||||
|
boolean invokeSuspendOfLambda = false;
|
||||||
|
FunctionDescriptor inlineSiteDescriptor = null;
|
||||||
if (inlineSiteContext instanceof MethodContext) {
|
if (inlineSiteContext instanceof MethodContext) {
|
||||||
originalInlineClass = CoroutineCodegenUtilKt
|
inlineSiteDescriptor = ((MethodContext) inlineSiteContext).getFunctionDescriptor();
|
||||||
.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(
|
originalInlineClass = CoroutineCodegenUtilKt
|
||||||
((MethodContext) inlineSiteContext).getFunctionDescriptor(), typeMapper);
|
.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(inlineSiteDescriptor, typeMapper);
|
||||||
|
invokeSuspendOfLambda = CoroutineCodegenUtilKt.isInvokeSuspendOfLambda(inlineSiteDescriptor);
|
||||||
}
|
}
|
||||||
if (originalInlineClass != null) {
|
if (originalInlineClass != null) {
|
||||||
returnType = typeMapper.mapType(originalInlineClass);
|
returnType = typeMapper.mapType(originalInlineClass);
|
||||||
returnKotlinType = originalInlineClass;
|
returnKotlinType = originalInlineClass;
|
||||||
} else {
|
} else if (!invokeSuspendOfLambda) {
|
||||||
returnType = nonLocalReturn.returnType.getType();
|
returnType = nonLocalReturn.returnType.getType();
|
||||||
returnKotlinType = nonLocalReturn.returnType.getKotlinType();
|
returnKotlinType = nonLocalReturn.returnType.getKotlinType();
|
||||||
|
} else {
|
||||||
|
returnType = OBJECT_TYPE;
|
||||||
|
returnKotlinType = inlineSiteDescriptor.getReturnType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -543,3 +543,12 @@ val EXPERIMENTAL_CONTINUATION_ASM_TYPE = StandardNames.CONTINUATION_INTERFACE_FQ
|
|||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val RELEASE_CONTINUATION_ASM_TYPE = StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.topLevelClassAsmType()
|
val RELEASE_CONTINUATION_ASM_TYPE = StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.topLevelClassAsmType()
|
||||||
|
|
||||||
|
fun FunctionDescriptor.isInvokeSuspendOfLambda(): Boolean {
|
||||||
|
if (this !is SimpleFunctionDescriptor) return false
|
||||||
|
if (valueParameters.size != 1 ||
|
||||||
|
valueParameters[0].name.asString() != SUSPEND_CALL_RESULT_NAME ||
|
||||||
|
name.asString() != "invokeSuspend"
|
||||||
|
) return false
|
||||||
|
return containingDeclaration is SyntheticClassDescriptorForLambda
|
||||||
|
}
|
||||||
Generated
+5
@@ -7577,6 +7577,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
|
public void testNonLocalReturn() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/nonLocalReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// IGNORE_BACKEND: JVM_IR, JS_IR
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
|
||||||
|
fun <T> builder(c: suspend () -> T): T {
|
||||||
|
var res: T? = null
|
||||||
|
c.startCoroutine(Continuation(EmptyCoroutineContext) {
|
||||||
|
res = it.getOrThrow()
|
||||||
|
})
|
||||||
|
return res!!
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> runSuspend(c: suspend () -> T): T {
|
||||||
|
return c()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("RESULT_CLASS_IN_RETURN_TYPE")
|
||||||
|
suspend fun foo(): Result<String> = runSuspend {
|
||||||
|
run { return@runSuspend Result.failure<String>(RuntimeException("OK")) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return try {
|
||||||
|
builder { foo() }.getOrThrow()
|
||||||
|
"FAIL"
|
||||||
|
} catch (e: RuntimeException) {
|
||||||
|
e.message!!
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -8292,6 +8292,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
|
public void testNonLocalReturn() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/nonLocalReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+5
@@ -8292,6 +8292,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
|
public void testNonLocalReturn() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/nonLocalReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+5
@@ -7577,6 +7577,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
|
public void testNonLocalReturn() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/nonLocalReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Generated
+5
@@ -6332,6 +6332,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
|
public void testNonLocalReturn() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/nonLocalReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Generated
+5
@@ -6332,6 +6332,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
|
public void testNonLocalReturn() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/nonLocalReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+5
@@ -6332,6 +6332,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
|
public void testNonLocalReturn() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/nonLocalReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/direct")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user