[FIR] Add synthetic else branch to when if it's missing

This change is needed for correct work of data flow, because for
  non-exhaustive when there is a else branch in terms of control flow
  graph.

This change leads to some errors when when is actually exhaustive, but
  we still add else branch. Those errors will be gone when exhaustive
  checker will be introduced
This commit is contained in:
Dmitriy Novozhilov
2019-08-08 14:02:01 +03:00
parent e904e638e9
commit 38fa0122e8
4 changed files with 17 additions and 10 deletions

View File

@@ -943,6 +943,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
if (hasSubject) {
subject.bind(this)
}
var thereIsElseBranch = false
for (entry in expression.entries) {
val branch = entry.expression.toFirBlock()
branches += if (!entry.isElse) {
@@ -960,9 +961,13 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
FirWhenBranchImpl(entry, firCondition, branch)
}
} else {
thereIsElseBranch = true
FirWhenBranchImpl(entry, FirElseIfTrueCondition(null), branch)
}
}
if (!thereIsElseBranch) {
branches += FirWhenBranchImpl(null, FirElseIfTrueCondition(null), FirEmptyExpressionBlock())
}
}
}

View File

@@ -35,6 +35,8 @@ FILE: recursiveCallOnWhenWithSealedClass.kt
($subj$ is R|Maybe.Yeah|) -> {
<Unresolved name: meat>#
}
else -> {
}
}
}

View File

@@ -2,9 +2,9 @@ FILE fqName:<root> fileName:/whenCoercedToUnit.kt
FUN name:foo visibility:public modality:FINAL <> (x:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER name:x index:0 type:kotlin.Int
BLOCK_BODY
BLOCK type=kotlin.Int origin=WHEN
BLOCK type=kotlin.Unit origin=WHEN
VAR IR_TEMPORARY_VARIABLE name:tmp0_subject type:kotlin.Int [val]
WHEN type=kotlin.Int origin=WHEN
WHEN type=kotlin.Unit origin=WHEN
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp0_subject: kotlin.Int [val] declared in <root>.foo' type=kotlin.Int origin=null

View File

@@ -11,16 +11,16 @@ FILE fqName:<root> fileName:/kt24114.kt
BLOCK_BODY
WHILE label=null origin=WHILE_LOOP
condition: CONST Boolean type=kotlin.Boolean value=true
body: BLOCK type=kotlin.Int origin=WHEN
body: BLOCK type=kotlin.Unit origin=WHEN
VAR IR_TEMPORARY_VARIABLE name:tmp0_subject type:kotlin.Int [val]
WHEN type=kotlin.Int origin=WHEN
WHEN type=kotlin.Unit origin=WHEN
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp0_subject: kotlin.Int [val] declared in <root>.test1' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=1
then: BLOCK type=kotlin.Nothing origin=WHEN
then: BLOCK type=kotlin.Unit origin=WHEN
VAR IR_TEMPORARY_VARIABLE name:tmp1_subject type:kotlin.Int [val]
WHEN type=kotlin.Nothing origin=WHEN
WHEN type=kotlin.Unit origin=WHEN
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp1_subject: kotlin.Int [val] declared in <root>.test1' type=kotlin.Int origin=null
@@ -35,16 +35,16 @@ FILE fqName:<root> fileName:/kt24114.kt
BLOCK_BODY
WHILE label=null origin=WHILE_LOOP
condition: CONST Boolean type=kotlin.Boolean value=true
body: BLOCK type=kotlin.Int origin=WHEN
body: BLOCK type=kotlin.Unit origin=WHEN
VAR IR_TEMPORARY_VARIABLE name:tmp2_subject type:kotlin.Int [val]
WHEN type=kotlin.Int origin=WHEN
WHEN type=kotlin.Unit origin=WHEN
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp2_subject: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=1
then: BLOCK type=kotlin.Nothing origin=WHEN
then: BLOCK type=kotlin.Unit origin=WHEN
VAR IR_TEMPORARY_VARIABLE name:tmp3_subject type:kotlin.Int [val]
WHEN type=kotlin.Nothing origin=WHEN
WHEN type=kotlin.Unit origin=WHEN
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp3_subject: kotlin.Int [val] declared in <root>.test2' type=kotlin.Int origin=null