diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index aadb64b89e4..1bff5f4a925 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt index 2c85e9886d9..72fcdae73a5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt @@ -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 { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index e797a474f52..f9bc604834e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -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 { - 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()) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index ada0a25eb20..409b368bc2c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -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() } diff --git a/compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt b/compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt new file mode 100644 index 00000000000..8a47290fa88 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/inlineClasses/direct/defaultStub.kt @@ -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 +} diff --git a/compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt b/compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt new file mode 100644 index 00000000000..ee3d1ce8d44 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/inlineClasses/resume/defaultStub.kt @@ -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 { + it.resume(IC(x)) + COROUTINE_SUSPENDED +} + +fun box(): String { + var res = "" + suspend { res = foo().s }.startCoroutine(Continuation(EmptyCoroutineContext) { it.getOrThrow() }) + return res +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index a751d645f12..3c0461fc98b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 8aa2e5220f1..5ef515f2b9f 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 0c0a9891b93..23ed4dad442 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index a708841a4e5..bd1fea93dba 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -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"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 38d89fd8b8a..91244aecc94 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -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"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 4fb00b1eb71..1f164476833 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -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");