JVM_IR: expect unboxed return value from suspend default stubs
#KT-47206 Fixed
This commit is contained in:
+12
@@ -10484,6 +10484,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/createOverride.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
@@ -10776,6 +10782,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/createOverride.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
|
||||
+8
-11
@@ -191,17 +191,14 @@ internal fun createFakeContinuation(context: JvmBackendContext): IrExpression =
|
||||
)
|
||||
|
||||
internal fun IrFunction.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(): IrType? {
|
||||
if (!isSuspend) return null
|
||||
// Check whether we in fact return inline class
|
||||
val unboxedReturnType = InlineClassAbi.unboxType(returnType.makeNotNull()) ?: return null
|
||||
// Force boxing for primitives. NOTE: this also forbids unboxing a nullable inline class into a nullable primitive.
|
||||
if (unboxedReturnType.isPrimitiveType()) return null
|
||||
// Force boxing for nullable inline class types with nullable underlying type
|
||||
if (returnType.isNullable() && unboxedReturnType.isNullable()) return null
|
||||
// Force boxing if the function overrides function with different type modulo nullability ignoring type parameters
|
||||
if ((this as? IrSimpleFunction)?.overridesReturningDifferentType(returnType) != false) return null
|
||||
// Don't box other inline classes
|
||||
return returnType
|
||||
if (this !is IrSimpleFunction || !isSuspend) return null
|
||||
// Unlike `suspendFunctionOriginal()`, this also maps `$default` stubs to the original function.
|
||||
val original = attributeOwnerId as IrSimpleFunction
|
||||
val unboxedReturnType = InlineClassAbi.unboxType(original.returnType) ?: return null
|
||||
// 1. Can't unbox into a primitive, since suspend functions have to return a reference type.
|
||||
// 2. Force boxing if the function overrides function with different type modulo nullability ignoring type parameters
|
||||
if (unboxedReturnType.isPrimitiveType() || original.overridesReturningDifferentType(original.returnType)) return null
|
||||
return original.returnType
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.overridesReturningDifferentType(returnType: IrType): Boolean {
|
||||
|
||||
+10
-18
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.constantValue
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.isMultifileBridge
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.*
|
||||
@@ -488,8 +487,7 @@ class ExpressionCodegen(
|
||||
|
||||
callGenerator.genCall(callable, this, expression, isInsideCondition)
|
||||
|
||||
val unboxedInlineClassIrType =
|
||||
callee.suspendFunctionOriginal().originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
|
||||
val unboxedInlineClassIrType = callee.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
|
||||
|
||||
if (isSuspensionPoint != SuspensionPointKind.NEVER) {
|
||||
addSuspendMarker(mv, isStartNotEnd = false, isSuspensionPoint == SuspensionPointKind.NOT_INLINE)
|
||||
@@ -519,21 +517,15 @@ class ExpressionCodegen(
|
||||
wrapJavaClassesIntoKClasses(mv)
|
||||
MaterialValue(this, AsmTypes.K_CLASS_ARRAY_TYPE, expression.type)
|
||||
}
|
||||
unboxedInlineClassIrType != null && !irFunction.isNonBoxingSuspendDelegation() -> {
|
||||
if (!irFunction.shouldContainSuspendMarkers()) {
|
||||
// Since the coroutine transformer won't run, we need to do this manually.
|
||||
mv.generateCoroutineSuspendedCheck(state.languageVersionSettings)
|
||||
unboxedInlineClassIrType != null && !irFunction.isNonBoxingSuspendDelegation() ->
|
||||
MaterialValue(this, unboxedInlineClassIrType.asmType, unboxedInlineClassIrType).apply {
|
||||
if (!irFunction.shouldContainSuspendMarkers()) {
|
||||
// Since the coroutine transformer won't run, we need to do this manually.
|
||||
mv.generateCoroutineSuspendedCheck(state.languageVersionSettings)
|
||||
}
|
||||
mv.checkcast(type)
|
||||
}
|
||||
mv.checkcast(unboxedInlineClassIrType.asmType)
|
||||
if (irFunction.isInvokeSuspendOfContinuation()) {
|
||||
// TODO: why is simply materializing the value with type `Object` not enough? This branch shouldn't be needed.
|
||||
StackValue.boxInlineClass(unboxedInlineClassIrType, mv, typeMapper)
|
||||
MaterialValue(this, callable.asmMethod.returnType, callable.returnType)
|
||||
} else {
|
||||
MaterialValue(this, unboxedInlineClassIrType.asmType, unboxedInlineClassIrType)
|
||||
}
|
||||
}
|
||||
expression.symbol.owner.resultIsActuallyAny(null) == true ->
|
||||
callee.resultIsActuallyAny(null) == true ->
|
||||
MaterialValue(this, callable.asmMethod.returnType, context.irBuiltIns.anyNType)
|
||||
else ->
|
||||
MaterialValue(this, callable.asmMethod.returnType, callable.returnType)
|
||||
@@ -907,7 +899,7 @@ class ExpressionCodegen(
|
||||
}
|
||||
|
||||
private fun IrFunction.returnAsmAndIrTypes(): Pair<Type, IrType> {
|
||||
val unboxedInlineClass = suspendFunctionOriginal().originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
|
||||
val unboxedInlineClass = originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
|
||||
// In case of non-boxing delegation, the return type of the tail call was considered to be `Object`,
|
||||
// so that's also what we'll return here to avoid casts/unboxings/etc.
|
||||
if (unboxedInlineClass != null && !isNonBoxingSuspendDelegation()) {
|
||||
|
||||
+1
-1
@@ -179,7 +179,7 @@ class IrExpressionLambdaImpl(
|
||||
val freeAsmParameters = asmMethod.argumentTypes.let { it.take(startCapture) + it.drop(endCapture) }
|
||||
// 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 unboxedReturnType = function.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
|
||||
val unboxedAsmReturnType = unboxedReturnType?.let(codegen.typeMapper::mapType)
|
||||
invokeMethod = Method(asmMethod.name, unboxedAsmReturnType ?: asmMethod.returnType, freeAsmParameters.toTypedArray())
|
||||
invokeMethodParameters = freeParameters.map { it.type.toIrBasedKotlinType() }
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
import kotlin.coroutines.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(Continuation(EmptyCoroutineContext) {
|
||||
it.getOrThrow()
|
||||
})
|
||||
}
|
||||
|
||||
inline class IC(val s: String)
|
||||
|
||||
suspend fun foo(x: String = "OK") = IC(x)
|
||||
|
||||
fun box(): String {
|
||||
var res = ""
|
||||
builder {
|
||||
res = foo().s
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
inline class IC(val s: String)
|
||||
|
||||
suspend fun foo(x: String = "OK") = suspendCoroutineUninterceptedOrReturn<IC> {
|
||||
it.resume(IC(x))
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = ""
|
||||
suspend { res = foo().s }.startCoroutine(Continuation(EmptyCoroutineContext) { it.getOrThrow() })
|
||||
return res
|
||||
}
|
||||
+12
@@ -10484,6 +10484,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/createOverride.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
@@ -10776,6 +10782,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/createOverride.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
|
||||
+12
@@ -10484,6 +10484,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/createOverride.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
@@ -10776,6 +10782,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/createOverride.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
|
||||
+10
@@ -8296,6 +8296,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/createOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/genericOverrideSuspendFun.kt");
|
||||
@@ -8544,6 +8549,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/createOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/genericOverrideSuspendFun.kt");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+10
@@ -7395,6 +7395,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/createOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/genericOverrideSuspendFun.kt");
|
||||
@@ -7638,6 +7643,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/createOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/genericOverrideSuspendFun.kt");
|
||||
|
||||
Generated
+10
@@ -6801,6 +6801,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/createOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/genericOverrideSuspendFun.kt");
|
||||
@@ -7044,6 +7049,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/createOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/genericOverrideSuspendFun.kt");
|
||||
|
||||
Generated
+10
@@ -6801,6 +6801,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/createOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/genericOverrideSuspendFun.kt");
|
||||
@@ -7044,6 +7049,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/createOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultStub.kt")
|
||||
public void testDefaultStub() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericOverrideSuspendFun.kt")
|
||||
public void testGenericOverrideSuspendFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/genericOverrideSuspendFun.kt");
|
||||
|
||||
Reference in New Issue
Block a user