JVM_IR: do not handle Nothing in suspend tail call bridges
Else they wouldn't be tail call, would they?
This commit is contained in:
Generated
+5
@@ -6706,6 +6706,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspensionInsideSafeCall.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("tailCallToNothing.kt")
|
||||
public void testTailCallToNothing() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/tailCallToNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines");
|
||||
|
||||
+6
-4
@@ -19,11 +19,13 @@ import org.jetbrains.kotlin.ir.types.isNothing
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
class KotlinNothingValueExceptionLowering(val backendContext: CommonBackendContext) : BodyLoweringPass {
|
||||
class KotlinNothingValueExceptionLowering(
|
||||
val backendContext: CommonBackendContext, val skip: (IrDeclaration) -> Boolean = { false }
|
||||
) : BodyLoweringPass {
|
||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||
irBody.transformChildrenVoid(
|
||||
Transformer((container as IrSymbolDeclaration<*>).symbol)
|
||||
)
|
||||
if (!skip(container)) {
|
||||
irBody.transformChildrenVoid(Transformer((container as IrSymbolDeclaration<*>).symbol))
|
||||
}
|
||||
}
|
||||
|
||||
private inner class Transformer(val parent: IrSymbol) : IrElementTransformerVoid() {
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase
|
||||
import org.jetbrains.kotlin.backend.common.lower.optimizations.foldConstantLoweringPhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.shouldContainSuspendMarkers
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.*
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
@@ -262,8 +263,8 @@ private val tailrecPhase = makeIrFilePhase(
|
||||
description = "Handle tailrec calls"
|
||||
)
|
||||
|
||||
private val kotlinNothingValueExceptionPhase = makeIrFilePhase(
|
||||
::KotlinNothingValueExceptionLowering,
|
||||
private val kotlinNothingValueExceptionPhase = makeIrFilePhase<CommonBackendContext>(
|
||||
{ context -> KotlinNothingValueExceptionLowering(context) { it is IrFunction && !it.shouldContainSuspendMarkers() } },
|
||||
name = "KotlinNothingValueException",
|
||||
description = "Throw proper exception for calls returning value of type 'kotlin.Nothing'"
|
||||
)
|
||||
|
||||
+1
-4
@@ -449,12 +449,9 @@ class ExpressionCodegen(
|
||||
}
|
||||
|
||||
return when {
|
||||
expression.type.isNothing() -> {
|
||||
unitValue
|
||||
}
|
||||
expression is IrConstructorCall ->
|
||||
MaterialValue(this, asmType, expression.type)
|
||||
expression.type.isUnit() && irFunction.shouldContainSuspendMarkers() -> {
|
||||
(expression.type.isNothing() || expression.type.isUnit()) && irFunction.shouldContainSuspendMarkers() -> {
|
||||
// NewInference allows casting `() -> T` to `() -> Unit`. A CHECKCAST here will fail.
|
||||
// Also, if the callee is a suspend function with a suspending tail call, the next `resumeWith`
|
||||
// will continue from here, but the value passed to it might not have been `Unit`. An exception
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
suspend fun suspendThenThrow(): Nothing {
|
||||
suspendCoroutineUninterceptedOrReturn<Unit> {
|
||||
it.resume(Unit)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
throw RuntimeException()
|
||||
}
|
||||
|
||||
suspend fun foo(x: Int = 1): Nothing = suspendThenThrow()
|
||||
|
||||
interface I {
|
||||
suspend fun bar(): Nothing
|
||||
}
|
||||
|
||||
class C : I by (object : I {
|
||||
override suspend fun bar(): Nothing = suspendThenThrow()
|
||||
})
|
||||
|
||||
var result = ""
|
||||
|
||||
fun box(): String {
|
||||
suspend {
|
||||
try { foo() } catch (e: RuntimeException) { result += "O" }
|
||||
try { C().bar() } catch (e: RuntimeException) { result += "K" }
|
||||
}.startCoroutine(EmptyContinuation)
|
||||
return result
|
||||
}
|
||||
+5
@@ -7136,6 +7136,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspensionInsideSafeCall.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("tailCallToNothing.kt")
|
||||
public void testTailCallToNothing() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/tailCallToNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||
public void testTryCatchFinallyWithHandleResult_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines.experimental");
|
||||
|
||||
+5
@@ -7136,6 +7136,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspensionInsideSafeCall.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("tailCallToNothing.kt")
|
||||
public void testTailCallToNothing() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/tailCallToNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||
public void testTryCatchFinallyWithHandleResult_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines.experimental");
|
||||
|
||||
+5
@@ -6706,6 +6706,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspensionInsideSafeCall.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("tailCallToNothing.kt")
|
||||
public void testTailCallToNothing() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/tailCallToNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines");
|
||||
|
||||
Generated
+5
@@ -5656,6 +5656,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspensionInsideSafeCall.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("tailCallToNothing.kt")
|
||||
public void testTailCallToNothing() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/tailCallToNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines");
|
||||
|
||||
+5
@@ -5656,6 +5656,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspensionInsideSafeCall.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("tailCallToNothing.kt")
|
||||
public void testTailCallToNothing() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/tailCallToNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines");
|
||||
|
||||
Reference in New Issue
Block a user