KT-53255. Fix StackOverflow during IR verification from K2

In FIR we desugar when with multiple conditions leading to same block
as tree of OR expressions

Given
```
when(some) {
  "a", "b", "c" -> {}
  else -> {}
}
```

actually desugared into
```
when(val <subj> = some) {
  <subj> == "a" || <subj> == "b" || <subj> == "c" -> {}
  else -> {}
}
```

There is a multiple ways of how we can organize such expressions in FIR
Previously it was just nesting-chain of OR expressions

While the most efficient way in terms of required stack depth is
a balanced tree

KT-53255
This commit is contained in:
Simon Ogorodnik
2022-10-19 04:29:10 +02:00
committed by Space Team
parent ac8cae16ba
commit 2cf8f75a90
6 changed files with 67 additions and 61 deletions
+24 -24
View File
@@ -102,50 +102,50 @@ FILE fqName:<root> fileName:/when.kt
BRANCH
if: WHEN type=kotlin.Boolean origin=OROR
BRANCH
if: WHEN type=kotlin.Boolean origin=OROR
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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=1
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=2
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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=1
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=3
arg1: CONST Int type=kotlin.Int value=2
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=4
then: WHEN type=kotlin.Boolean origin=OROR
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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=3
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=4
then: CONST String type=kotlin.String value="1234"
BRANCH
if: WHEN type=kotlin.Boolean origin=OROR
BRANCH
if: WHEN type=kotlin.Boolean origin=OROR
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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=5
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: WHEN type=kotlin.Boolean origin=OROR
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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=5
arg1: CONST Int type=kotlin.Int value=6
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=6
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=7
arg1: CONST Int type=kotlin.Int value=7
then: CONST String type=kotlin.String value="567"
BRANCH
if: WHEN type=kotlin.Boolean origin=OROR
+11 -11
View File
@@ -38,20 +38,20 @@ fun testComma(x: Int): String {
when {
when {
when {
when {
EQEQ(arg0 = tmp1_subject, arg1 = 1) -> true
else -> EQEQ(arg0 = tmp1_subject, arg1 = 2)
} -> true
else -> EQEQ(arg0 = tmp1_subject, arg1 = 3)
EQEQ(arg0 = tmp1_subject, arg1 = 1) -> true
else -> EQEQ(arg0 = tmp1_subject, arg1 = 2)
} -> true
else -> EQEQ(arg0 = tmp1_subject, arg1 = 4)
else -> when {
EQEQ(arg0 = tmp1_subject, arg1 = 3) -> true
else -> EQEQ(arg0 = tmp1_subject, arg1 = 4)
}
} -> "1234"
when {
when {
EQEQ(arg0 = tmp1_subject, arg1 = 5) -> true
else -> EQEQ(arg0 = tmp1_subject, arg1 = 6)
} -> true
else -> EQEQ(arg0 = tmp1_subject, arg1 = 7)
EQEQ(arg0 = tmp1_subject, arg1 = 5) -> true
else -> when {
EQEQ(arg0 = tmp1_subject, arg1 = 6) -> true
else -> EQEQ(arg0 = tmp1_subject, arg1 = 7)
}
} -> "567"
when {
EQEQ(arg0 = tmp1_subject, arg1 = 8) -> true