Ignore unreachable code on tail call optimization
#KT-21759: Fixed
This commit is contained in:
+9
-2
@@ -41,6 +41,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
import org.jetbrains.org.objectweb.asm.tree.*
|
import org.jetbrains.org.objectweb.asm.tree.*
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
|
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||||
|
|
||||||
@@ -689,14 +690,16 @@ private fun allSuspensionPointsAreTailCalls(
|
|||||||
methodNode: MethodNode,
|
methodNode: MethodNode,
|
||||||
suspensionPoints: List<SuspensionPoint>
|
suspensionPoints: List<SuspensionPoint>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val safelyReachableReturns = findSafelyReachableReturns(methodNode)
|
|
||||||
val sourceFrames = MethodTransformer.analyze(thisName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
val sourceFrames = MethodTransformer.analyze(thisName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
||||||
|
val safelyReachableReturns = findSafelyReachableReturns(methodNode, sourceFrames)
|
||||||
|
|
||||||
val instructions = methodNode.instructions
|
val instructions = methodNode.instructions
|
||||||
return suspensionPoints.all { suspensionPoint ->
|
return suspensionPoints.all { suspensionPoint ->
|
||||||
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
|
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
|
||||||
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
|
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
|
||||||
|
|
||||||
|
if (isUnreachable(beginIndex, sourceFrames)) return@all true
|
||||||
|
|
||||||
val insideTryBlock = methodNode.tryCatchBlocks.any { block ->
|
val insideTryBlock = methodNode.tryCatchBlocks.any { block ->
|
||||||
val tryBlockStartIndex = instructions.indexOf(block.start)
|
val tryBlockStartIndex = instructions.indexOf(block.start)
|
||||||
val tryBlockEndIndex = instructions.indexOf(block.end)
|
val tryBlockEndIndex = instructions.indexOf(block.end)
|
||||||
@@ -728,7 +731,7 @@ internal class IgnoringCopyOperationSourceInterpreter : SourceInterpreter() {
|
|||||||
*
|
*
|
||||||
* @return indices of safely reachable returns for each instruction in the method node
|
* @return indices of safely reachable returns for each instruction in the method node
|
||||||
*/
|
*/
|
||||||
private fun findSafelyReachableReturns(methodNode: MethodNode): Array<Set<Int>?> {
|
private fun findSafelyReachableReturns(methodNode: MethodNode, sourceFrames: Array<Frame<SourceValue?>?>): Array<Set<Int>?> {
|
||||||
val controlFlowGraph = ControlFlowGraph.build(methodNode)
|
val controlFlowGraph = ControlFlowGraph.build(methodNode)
|
||||||
|
|
||||||
val insns = methodNode.instructions
|
val insns = methodNode.instructions
|
||||||
@@ -736,6 +739,7 @@ private fun findSafelyReachableReturns(methodNode: MethodNode): Array<Set<Int>?>
|
|||||||
val insn = insns[index]
|
val insn = insns[index]
|
||||||
|
|
||||||
if (insn.opcode == Opcodes.ARETURN) {
|
if (insn.opcode == Opcodes.ARETURN) {
|
||||||
|
if (isUnreachable(index, sourceFrames)) return@init null
|
||||||
return@init setOf(index)
|
return@init setOf(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -770,6 +774,9 @@ private fun findSafelyReachableReturns(methodNode: MethodNode): Array<Set<Int>?>
|
|||||||
return reachableReturnsIndices
|
return reachableReturnsIndices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check whether this instruction is unreachable, i.e. there is no path leading to this instruction
|
||||||
|
internal fun isUnreachable(index: Int, sourceFrames: Array<Frame<SourceValue?>?>) = sourceFrames[index] == null
|
||||||
|
|
||||||
private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode): Boolean {
|
private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode): Boolean {
|
||||||
val insns = methodNode.instructions
|
val insns = methodNode.instructions
|
||||||
val index = insns.indexOf(this)
|
val index = insns.indexOf(this)
|
||||||
|
|||||||
+3
-1
@@ -112,7 +112,9 @@ object ReturnUnitMethodTransformer : MethodTransformer() {
|
|||||||
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
|
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
|
||||||
val frames = analyze(internalClassName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
val frames = analyze(internalClassName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
||||||
return pops.keysToMap {
|
return pops.keysToMap {
|
||||||
frames[methodNode.instructions.indexOf(it)].getStack(0).insns
|
val index = methodNode.instructions.indexOf(it)
|
||||||
|
if (isUnreachable(index, frames)) return@keysToMap emptySet<AbstractInsnNode>()
|
||||||
|
frames[index].getStack(0).insns
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_COROUTINES
|
||||||
|
import helpers.*
|
||||||
|
import kotlin.coroutines.experimental.*
|
||||||
|
import kotlin.coroutines.experimental.intrinsics.*
|
||||||
|
|
||||||
|
suspend fun twoReturns(c: suspend () -> Unit) {
|
||||||
|
return c()
|
||||||
|
throw RuntimeException("FAIL 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun builder(c: suspend () -> Unit) {
|
||||||
|
c.startCoroutine(EmptyContinuation)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var res = "FAIL"
|
||||||
|
builder {
|
||||||
|
twoReturns {
|
||||||
|
res = "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
suspend fun empty() {}
|
||||||
|
suspend fun withoutReturn() {
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun twoReturns() {
|
||||||
|
return empty()
|
||||||
|
return empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun notTailCall() {
|
||||||
|
empty()
|
||||||
|
return empty()
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun lambdaAsParameter(c: suspend () -> Unit) {
|
||||||
|
c()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun lambdaAsParameterNotTailCall(c: suspend () -> Unit) {
|
||||||
|
c()
|
||||||
|
return c()
|
||||||
|
c()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun lambdaAsParameterReturn(c: suspend () -> Unit) {
|
||||||
|
return c()
|
||||||
|
c()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun returnsInt() = 42
|
||||||
|
suspend fun callsIntNotTailCall() {
|
||||||
|
returnsInt()
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun multipleExitPoints(b: Boolean) {
|
||||||
|
if (b) empty() else withoutReturn()
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun multipleExitPointsNotTailCall(b: Boolean) {
|
||||||
|
if (b) empty() else returnsInt()
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ordinary() = 1
|
||||||
|
inline fun ordinaryInline() {
|
||||||
|
ordinary()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun multipleExitPointsWithOrdinaryInline(b: Boolean) {
|
||||||
|
if (b) empty() else ordinaryInline()
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun multipleExitPointsWhen(i: Int) {
|
||||||
|
when (i) {
|
||||||
|
1 -> empty()
|
||||||
|
2 -> twoReturns()
|
||||||
|
3 -> withoutReturn()
|
||||||
|
else -> lambdaAsParameter {}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> generic(): T = TODO()
|
||||||
|
suspend fun useGenericReturningUnit() {
|
||||||
|
generic<Unit>()
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Generic<T> {
|
||||||
|
suspend fun foo(): T = TODO()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun useGenericClass(g: Generic<Unit>) {
|
||||||
|
g.foo()
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> genericInferType(c: () -> T): T = TODO()
|
||||||
|
suspend fun useGenericInferType() {
|
||||||
|
genericInferType {}
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun nullableUnit(): Unit? = null
|
||||||
|
suspend fun useNullableUnit() {
|
||||||
|
nullableUnit()
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun useRunRunRunRunRun() {
|
||||||
|
run {
|
||||||
|
run {
|
||||||
|
run {
|
||||||
|
run {
|
||||||
|
run {
|
||||||
|
empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
empty()
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class Generic {
|
||||||
|
public method <init>(): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method foo(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class UnreachableKt$callsIntNotTailCall$1 {
|
||||||
|
synthetic field data: java.lang.Object
|
||||||
|
synthetic field exception: java.lang.Throwable
|
||||||
|
inner class UnreachableKt$callsIntNotTailCall$1
|
||||||
|
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||||
|
synthetic final method getLabel(): int
|
||||||
|
synthetic final method setLabel(p0: int): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class UnreachableKt$lambdaAsParameterNotTailCall$1 {
|
||||||
|
field L$0: java.lang.Object
|
||||||
|
synthetic field data: java.lang.Object
|
||||||
|
synthetic field exception: java.lang.Throwable
|
||||||
|
inner class UnreachableKt$lambdaAsParameterNotTailCall$1
|
||||||
|
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||||
|
synthetic final method getLabel(): int
|
||||||
|
synthetic final method setLabel(p0: int): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class UnreachableKt$multipleExitPointsNotTailCall$1 {
|
||||||
|
field Z$0: boolean
|
||||||
|
synthetic field data: java.lang.Object
|
||||||
|
synthetic field exception: java.lang.Throwable
|
||||||
|
inner class UnreachableKt$multipleExitPointsNotTailCall$1
|
||||||
|
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||||
|
synthetic final method getLabel(): int
|
||||||
|
synthetic final method setLabel(p0: int): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class UnreachableKt$multipleExitPointsWhen$2 {
|
||||||
|
inner class UnreachableKt$multipleExitPointsWhen$2
|
||||||
|
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||||
|
public final @org.jetbrains.annotations.Nullable method invoke(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class UnreachableKt$notTailCall$1 {
|
||||||
|
synthetic field data: java.lang.Object
|
||||||
|
synthetic field exception: java.lang.Throwable
|
||||||
|
inner class UnreachableKt$notTailCall$1
|
||||||
|
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||||
|
synthetic final method getLabel(): int
|
||||||
|
synthetic final method setLabel(p0: int): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class UnreachableKt$useGenericInferType$2 {
|
||||||
|
public final static field INSTANCE: UnreachableKt$useGenericInferType$2
|
||||||
|
inner class UnreachableKt$useGenericInferType$2
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public synthetic method invoke(): java.lang.Object
|
||||||
|
public final method invoke(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class UnreachableKt$useNullableUnit$1 {
|
||||||
|
synthetic field data: java.lang.Object
|
||||||
|
synthetic field exception: java.lang.Throwable
|
||||||
|
inner class UnreachableKt$useNullableUnit$1
|
||||||
|
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||||
|
synthetic final method getLabel(): int
|
||||||
|
synthetic final method setLabel(p0: int): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class UnreachableKt {
|
||||||
|
inner class UnreachableKt$callsIntNotTailCall$1
|
||||||
|
inner class UnreachableKt$lambdaAsParameterNotTailCall$1
|
||||||
|
inner class UnreachableKt$multipleExitPointsNotTailCall$1
|
||||||
|
inner class UnreachableKt$multipleExitPointsWhen$2
|
||||||
|
inner class UnreachableKt$notTailCall$1
|
||||||
|
inner class UnreachableKt$useGenericInferType$2
|
||||||
|
inner class UnreachableKt$useNullableUnit$1
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method callsIntNotTailCall(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method empty(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method genericInferType(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method lambdaAsParameter(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method lambdaAsParameterNotTailCall(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method lambdaAsParameterReturn(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method multipleExitPoints(p0: boolean, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method multipleExitPointsNotTailCall(p0: boolean, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method multipleExitPointsWhen(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method multipleExitPointsWithOrdinaryInline(p0: boolean, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method notTailCall(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method nullableUnit(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static method ordinary(): int
|
||||||
|
public final static method ordinaryInline(): void
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method returnsInt(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method twoReturns(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method useGenericClass(@org.jetbrains.annotations.NotNull p0: Generic, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method useGenericInferType(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method useGenericReturningUnit(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method useNullableUnit(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method useRunRunRunRunRun(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method withoutReturn(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
|
||||||
|
}
|
||||||
Generated
+6
@@ -6394,6 +6394,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unreachable.kt")
|
||||||
|
public void testUnreachable() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/unreachable.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
|
||||||
|
|||||||
+6
@@ -6394,6 +6394,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unreachable.kt")
|
||||||
|
public void testUnreachable() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/unreachable.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
|
||||||
|
|||||||
+6
@@ -169,6 +169,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unreachable.kt")
|
||||||
|
public void testUnreachable() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/unreachable.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/bytecodeListing/annotations")
|
@TestMetadata("compiler/testData/codegen/bytecodeListing/annotations")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+6
@@ -6394,6 +6394,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unreachable.kt")
|
||||||
|
public void testUnreachable() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/unreachable.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
|
||||||
|
|||||||
+6
@@ -6952,6 +6952,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unreachable.kt")
|
||||||
|
public void testUnreachable() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/unreachable.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
|
||||||
|
|||||||
Reference in New Issue
Block a user