Fir2Ir: generate coercion to Unit for when branches if needed

Before this change, it could happen that `when` of type Unit has a
branch whose type is not Unit. This can lead to problems in IR
lowerings, for example PolymorphicSignatureLowering which is very
reliant on the correct types of expressions and placement of coercions
to Unit (KT-59218).
This commit is contained in:
Alexander Udalov
2023-06-28 15:12:10 +02:00
committed by Space Team
parent 5513740659
commit 79fa2b6db0
3 changed files with 10 additions and 11 deletions
@@ -1092,8 +1092,12 @@ class Fir2IrVisitor(
if (whenExpression.branches.isEmpty()) {
return@convertWithOffsets IrBlockImpl(startOffset, endOffset, irBuiltIns.unitType, origin)
}
val whenExpressionType =
if (whenExpression.isProperlyExhaustive && whenExpression.branches.none {
it.condition is FirElseIfTrueCondition && it.result.statements.isEmpty()
}) whenExpression.typeRef else session.builtinTypes.unitType
val irBranches = whenExpression.branches.mapTo(mutableListOf()) { branch ->
branch.toIrWhenBranch(whenExpression.typeRef)
branch.toIrWhenBranch(whenExpressionType)
}
if (whenExpression.isProperlyExhaustive && whenExpression.branches.none { it.condition is FirElseIfTrueCondition }) {
val irResult = IrCallImpl(
@@ -1106,14 +1110,7 @@ class Fir2IrVisitor(
IrConstImpl.boolean(startOffset, endOffset, irBuiltIns.booleanType, true), irResult
)
}
generateWhen(
startOffset, endOffset, origin,
subjectVariable, irBranches,
if (whenExpression.isProperlyExhaustive && whenExpression.branches.none {
it.condition is FirElseIfTrueCondition && it.result.statements.isEmpty()
}
) whenExpression.typeRef.toIrType() else irBuiltIns.unitType
)
generateWhen(startOffset, endOffset, origin, subjectVariable, irBranches, whenExpressionType.toIrType())
}
}.also {
whenExpression.accept(implicitCastInserter, it)
@@ -47,7 +47,8 @@ FILE fqName:<root> fileName:/ifElseIf.kt
WHEN type=kotlin.Unit origin=IF
BRANCH
if: GET_VAR 'flag: kotlin.Boolean declared in <root>.testEmptyBranches2' type=kotlin.Boolean origin=null
then: CONST Boolean type=kotlin.Boolean value=true
then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: BLOCK type=kotlin.Unit origin=null
@@ -24,7 +24,7 @@ fun testEmptyBranches2(flag: Boolean) {
else -> true
} /*~> Unit */
when {
flag -> true
flag -> true /*~> Unit */
else -> { // BLOCK
}
}
@@ -37,3 +37,4 @@ fun testEmptyBranches3(flag: Boolean) {
else -> true
} /*~> Unit */
}