From 11c4a2518d620fa22354b914e2f53192c7553b79 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Fri, 29 Jun 2018 12:21:08 +0300 Subject: [PATCH] Fixed bug in finally blocks lowering + test Return type must be taken from the function --- .../konan/lower/FinallyBlocksLowering.kt | 14 +++++++--- backend.native/tests/build.gradle | 5 ++++ .../codegen/try/returnsDifferentTypes.kt | 28 +++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 backend.native/tests/codegen/try/returnsDifferentTypes.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt index bdf0a2f3d96..e5417cce1ea 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt @@ -26,9 +26,6 @@ import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.ir.expressions.* @@ -38,6 +35,7 @@ import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -177,6 +175,14 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir return performHighLevelJump(tryScopes, 0, jump, startOffset, endOffset, value) } + private val IrReturnTarget.returnType: IrType + get() = when (this) { + is IrConstructor -> context.irBuiltIns.unitType + is IrFunction -> returnType + is IrReturnableBlock -> type + else -> error("Unknown ReturnTarget: $this") + } + private fun performHighLevelJump(tryScopes: List, index: Int, jump: HighLevelJump, @@ -188,7 +194,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir val currentTryScope = tryScopes[index] currentTryScope.jumps.getOrPut(jump) { - val type = value.type + val type = (jump as? Return)?.target?.owner?.returnType ?: value.type val symbol = getIrReturnableBlockSymbol(jump.toString(), type) with(currentTryScope) { irBuilder.run { diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 1c21187deb0..89530c70be3 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -1893,6 +1893,11 @@ task finally11(type: RunKonanTest) { source = "codegen/try/finally11.kt" } +task finally_returnsDifferentTypes(type: RunKonanTest) { + goldValue = "zzz\n42\n" + source = "codegen/try/returnsDifferentTypes.kt" +} + task scope1(type: RunKonanTest) { goldValue = "1\n" source = "codegen/dataflow/scope1.kt" diff --git a/backend.native/tests/codegen/try/returnsDifferentTypes.kt b/backend.native/tests/codegen/try/returnsDifferentTypes.kt new file mode 100644 index 00000000000..90f2835e7de --- /dev/null +++ b/backend.native/tests/codegen/try/returnsDifferentTypes.kt @@ -0,0 +1,28 @@ +package codegen.`try`.returnsDifferentTypes + +import kotlin.test.* + +class ReceiveChannel + +inline fun ReceiveChannel.consume(block: ReceiveChannel.() -> R): R { + try { + return block() + } + finally { + println("zzz") + } +} + +inline fun ReceiveChannel.elementAtOrElse(index: Int, defaultValue: (Int) -> E): E = + consume { + if (index < 0) + return defaultValue(index) + return 42 as E + } + +fun ReceiveChannel.elementAt(index: Int): E = + elementAtOrElse(index) { throw IndexOutOfBoundsException("qxx") } + +@Test fun runTest() { + println(ReceiveChannel().elementAt(0)) +} \ No newline at end of file