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");
|
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")
|
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||||
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines");
|
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.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
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) {
|
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||||
irBody.transformChildrenVoid(
|
if (!skip(container)) {
|
||||||
Transformer((container as IrSymbolDeclaration<*>).symbol)
|
irBody.transformChildrenVoid(Transformer((container as IrSymbolDeclaration<*>).symbol))
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class Transformer(val parent: IrSymbol) : IrElementTransformerVoid() {
|
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.loops.forLoopsPhase
|
||||||
import org.jetbrains.kotlin.backend.common.lower.optimizations.foldConstantLoweringPhase
|
import org.jetbrains.kotlin.backend.common.lower.optimizations.foldConstantLoweringPhase
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
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.backend.jvm.lower.*
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
@@ -262,8 +263,8 @@ private val tailrecPhase = makeIrFilePhase(
|
|||||||
description = "Handle tailrec calls"
|
description = "Handle tailrec calls"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val kotlinNothingValueExceptionPhase = makeIrFilePhase(
|
private val kotlinNothingValueExceptionPhase = makeIrFilePhase<CommonBackendContext>(
|
||||||
::KotlinNothingValueExceptionLowering,
|
{ context -> KotlinNothingValueExceptionLowering(context) { it is IrFunction && !it.shouldContainSuspendMarkers() } },
|
||||||
name = "KotlinNothingValueException",
|
name = "KotlinNothingValueException",
|
||||||
description = "Throw proper exception for calls returning value of type 'kotlin.Nothing'"
|
description = "Throw proper exception for calls returning value of type 'kotlin.Nothing'"
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-4
@@ -449,12 +449,9 @@ class ExpressionCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
expression.type.isNothing() -> {
|
|
||||||
unitValue
|
|
||||||
}
|
|
||||||
expression is IrConstructorCall ->
|
expression is IrConstructorCall ->
|
||||||
MaterialValue(this, asmType, expression.type)
|
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.
|
// 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`
|
// 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
|
// 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");
|
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")
|
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||||
public void testTryCatchFinallyWithHandleResult_1_2() throws Exception {
|
public void testTryCatchFinallyWithHandleResult_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines.experimental");
|
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");
|
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")
|
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||||
public void testTryCatchFinallyWithHandleResult_1_2() throws Exception {
|
public void testTryCatchFinallyWithHandleResult_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines.experimental");
|
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");
|
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")
|
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||||
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines");
|
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");
|
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")
|
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||||
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines");
|
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");
|
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")
|
@TestMetadata("tryCatchFinallyWithHandleResult.kt")
|
||||||
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
public void testTryCatchFinallyWithHandleResult_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt", "kotlin.coroutines");
|
||||||
|
|||||||
Reference in New Issue
Block a user