JVM_IR: expect unboxed return value from suspend default stubs
#KT-47206 Fixed
This commit is contained in:
+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() }
|
||||
|
||||
Reference in New Issue
Block a user