diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt index d6626e42f54..3287984e9bf 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt @@ -17,12 +17,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCatchImpl import org.jetbrains.kotlin.ir.expressions.impl.IrElseBranchImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl -import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl import org.jetbrains.kotlin.ir.visitors.IrElementTransformer /** @@ -38,21 +34,20 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformer * is converted into * * try {} - * catch (ex: Ex = LCA(Ex1, Ex2, Ex3)) { - * when (ex) { - * ex is Ex1 -> catch1((Ex1)ex) - * ex is Ex2 -> catch2((Ex2)ex) - * ex is Ex3 -> catch3((Ex3)ex) - * else throw ex [ | catch_dynamic(ex) ] + * catch ($p: dynamic) { + * when ($p) { + * ex is Ex1 -> catch1((Ex1)$p) + * ex is Ex2 -> catch2((Ex2)$p) + * ex is Ex3 -> catch3((Ex3)$p) + * else throw $p [ | catch_dynamic($p) ] * } * } * finally {} */ -class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPass { - val litTrue get() = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true) - val unitType = context.irBuiltIns.unitType - val nothingType = context.irBuiltIns.nothingType +class MultipleCatchesLowering(private val context: JsIrBackendContext) : FileLoweringPass { + private val litTrue get() = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true) + private val nothingType = context.irBuiltIns.nothingType override fun lower(irFile: IrFile) { irFile.transformChildren(object : IrElementTransformer { @@ -65,23 +60,21 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas override fun visitTry(aTry: IrTry, data: IrDeclarationParent): IrExpression { aTry.transformChildren(this, data) - if (aTry.catches.isEmpty()) return aTry.apply { assert(finallyExpression != null) } + if (aTry.catches.isEmpty()) return aTry.also { assert(it.finallyExpression != null) } - val commonType = mergeTypes(aTry.catches.map { it.catchParameter.type }) - - val pendingExceptionDeclaration = JsIrBuilder.buildVar(commonType, data, "\$p") + val pendingExceptionDeclaration = JsIrBuilder.buildVar(context.dynamicType, data, "\$p") val pendingException = { JsIrBuilder.buildGetValue(pendingExceptionDeclaration.symbol) } val branches = mutableListOf() + var isCaughtDynamic = false for (catch in aTry.catches) { assert(!catch.catchParameter.isVar) { "caught exception parameter has to be immutable" } val type = catch.catchParameter.type - val typeSymbol = type.classifierOrNull val castedPendingException = { if (type !is IrDynamicType) - buildImplicitCast(pendingException(), type, typeSymbol!!) + buildImplicitCast(pendingException(), type) else pendingException() } @@ -96,15 +89,15 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas if (type is IrDynamicType) { branches += IrElseBranchImpl(catch.startOffset, catch.endOffset, litTrue, catchBody) + isCaughtDynamic = true break } else { - val typeCheck = buildIsCheck(pendingException(), type, typeSymbol!!) + val typeCheck = buildIsCheck(pendingException(), type) branches += IrBranchImpl(catch.startOffset, catch.endOffset, typeCheck, catchBody) } } - - if (commonType !is IrDynamicType) { + if (!isCaughtDynamic) { val throwStatement = JsIrBuilder.buildThrow(nothingType, pendingException()) branches += IrElseBranchImpl(litTrue, JsIrBuilder.buildBlock(nothingType, listOf(throwStatement))) } @@ -118,28 +111,11 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas return aTry.run { IrTryImpl(startOffset, endOffset, type, tryResult, listOf(newCatch), finallyExpression) } } - private fun buildIsCheck(value: IrExpression, toType: IrType, toTypeSymbol: IrClassifierSymbol) = - JsIrBuilder.buildTypeOperator(context.irBuiltIns.booleanType, IrTypeOperator.INSTANCEOF, value, toType, toTypeSymbol) + private fun buildIsCheck(value: IrExpression, toType: IrType) = + JsIrBuilder.buildTypeOperator(context.irBuiltIns.booleanType, IrTypeOperator.INSTANCEOF, value, toType) - private fun buildImplicitCast(value: IrExpression, toType: IrType, toTypeSymbol: IrClassifierSymbol) = - JsIrBuilder.buildTypeOperator(toType, IrTypeOperator.IMPLICIT_CAST, value, toType, toTypeSymbol) - - private fun mergeTypes(types: List): IrType { - - return types.firstOrNull { it is IrDynamicType } ?: run { - - val superClassifier = - types.map { (it as IrSimpleType).classifier }.commonSuperclass().also { - assert(it.isSubtypeOfClass(context.irBuiltIns.throwableClass)) - } - - val typeArguments = if (superClassifier is IrClassSymbol) { - superClassifier.owner.typeParameters.map { IrStarProjectionImpl } - } else emptyList() - - return IrSimpleTypeImpl(superClassifier, false, typeArguments, emptyList()) - } - } + private fun buildImplicitCast(value: IrExpression, toType: IrType) = + JsIrBuilder.buildTypeOperator(toType, IrTypeOperator.IMPLICIT_CAST, value, toType) }, irFile) }