From b1b87becc84b7d797f8da1c04b5087faa05cdcac Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 21 Oct 2020 16:21:46 +0300 Subject: [PATCH] PSI2IR more JVM-like exhaustive when behavior KT-36840 --- .../ir/FirBytecodeTextTestGenerated.java | 5 + .../kotlin/fir/Fir2IrTextTestGenerated.java | 5 + .../BranchingExpressionGenerator.kt | 36 +-- .../when/exhaustiveWhenSpecialCases.kt | 91 +++++++ .../when/exhaustiveWhenUnitStatement.kt | 2 - .../exhaustiveWhenElseBranch.fir.txt | 222 ++++++++++++++++++ .../expressions/exhaustiveWhenElseBranch.kt | 79 +++++++ .../expressions/exhaustiveWhenElseBranch.txt | 217 +++++++++++++++++ .../codegen/BytecodeTextTestGenerated.java | 5 + .../ir/IrBytecodeTextTestGenerated.java | 5 + .../kotlin/ir/IrTextTestCaseGenerated.java | 5 + 11 files changed, 652 insertions(+), 20 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeText/when/exhaustiveWhenSpecialCases.kt create mode 100644 compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.fir.txt create mode 100644 compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.kt create mode 100644 compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.txt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBytecodeTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBytecodeTextTestGenerated.java index 712fe046756..20dc3db9a96 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBytecodeTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBytecodeTextTestGenerated.java @@ -4748,6 +4748,11 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/when/exhaustiveWhenReturn.kt"); } + @TestMetadata("exhaustiveWhenSpecialCases.kt") + public void testExhaustiveWhenSpecialCases() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/when/exhaustiveWhenSpecialCases.kt"); + } + @TestMetadata("exhaustiveWhenUnit.kt") public void testExhaustiveWhenUnit() throws Exception { runTest("compiler/testData/codegen/bytecodeText/when/exhaustiveWhenUnit.kt"); diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java index 12d8d3f7bbc..bfb801447b4 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java @@ -917,6 +917,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/expressions/equals.kt"); } + @TestMetadata("exhaustiveWhenElseBranch.kt") + public void testExhaustiveWhenElseBranch() throws Exception { + runTest("compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.kt"); + } + @TestMetadata("extFunInvokeAsFun.kt") public void testExtFunInvokeAsFun() throws Exception { runTest("compiler/testData/ir/irText/expressions/extFunInvokeAsFun.kt"); diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt index 26d1d0de2d1..da3dbbde25c 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt @@ -102,10 +102,12 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta getExpressionTypeWithCoercionToUnitOrFail(expression).toIrType(), IrStatementOrigin.WHEN ) + var hasExplicitElseBranch = false for (ktEntry in expression.entries) { if (ktEntry.isElse) { val irElseResult = ktEntry.expression!!.genExpr() irWhen.branches.add(elseBranch(irElseResult)) + hasExplicitElseBranch = true break } @@ -122,7 +124,9 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta val irBranchResult = ktEntry.expression!!.genExpr() irWhen.branches.add(IrBranchImpl(irBranchCondition!!, irBranchResult)) } - addElseBranchForExhaustiveWhenIfNeeded(irWhen, expression) + if (!hasExplicitElseBranch) { + addElseBranchForExhaustiveWhenIfNeeded(irWhen, expression) + } return generateWhenBody(expression, irSubject, irWhen) } @@ -138,26 +142,22 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta } private fun addElseBranchForExhaustiveWhenIfNeeded(irWhen: IrWhen, whenExpression: KtWhenExpression) { - if (irWhen.branches.filterIsInstance().isEmpty()) { - //TODO: check condition: seems it's safe to always generate exception - val isExhaustive = whenExpression.isExhaustiveWhen() - - if (isExhaustive) { - val call = IrCallImpl.fromSymbolDescriptor( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, - context.irBuiltIns.nothingType, - context.irBuiltIns.noWhenBranchMatchedExceptionSymbol - ) - irWhen.branches.add(elseBranch(call)) - } + val isUsedAsExpression = true == get(BindingContext.USED_AS_EXPRESSION, whenExpression) + val isImplicitElseRequired = + if (isUsedAsExpression) + true == get(BindingContext.EXHAUSTIVE_WHEN, whenExpression) + else + true == get(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, whenExpression) + if (isImplicitElseRequired) { + val call = IrCallImpl.fromSymbolDescriptor( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + context.irBuiltIns.nothingType, + context.irBuiltIns.noWhenBranchMatchedExceptionSymbol + ) + irWhen.branches.add(elseBranch(call)) } } - private fun KtWhenExpression.isExhaustiveWhen(): Boolean = - elseExpression != null // TODO front-end should provide correct exhaustiveness information - || true == get(BindingContext.EXHAUSTIVE_WHEN, this) - || true == get(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, this) - private fun generateWhenBody(expression: KtWhenExpression, irSubject: IrVariable?, irWhen: IrWhen): IrExpression = if (irSubject == null) { if (irWhen.branches.isEmpty()) diff --git a/compiler/testData/codegen/bytecodeText/when/exhaustiveWhenSpecialCases.kt b/compiler/testData/codegen/bytecodeText/when/exhaustiveWhenSpecialCases.kt new file mode 100644 index 00000000000..b006c3d456a --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/when/exhaustiveWhenSpecialCases.kt @@ -0,0 +1,91 @@ +// IGNORE_BACKEND_FIR: JVM_IR + +enum class A { V1 } + +fun testVariableAssignment_throws(a: A) { + val x: Int + when (a) { + A.V1 -> x = 11 + // else -> throw + } +} + +fun testStatement_empty(a: A) { + when (a) { + A.V1 -> 1 + // else -> {} + } +} + +fun testParenthesized_throwsJvm(a: A) { + (when (a) { + A.V1 -> 1 + // JVM: else -> throw + // JVM_IR: else -> {} + }) +} + +fun testAnnotated_throwsJvm(a: A) { + @Suppress("") when (a) { + A.V1 -> 1 + // JVM: else -> throw + // JVM_IR: else -> {} + } +} + +fun testExpression_throws(a: A) = + when (a) { + A.V1 -> 1 + // else -> throw + } + +fun testIfTheElseStatement_empty(a: A, flag: Boolean) { + if (flag) + 0 + else { + when (a) { + A.V1 -> 1 + // else -> {} + } + } +} + +fun testIfTheElseParenthesized_throwsJvm(a: A, flag: Boolean) { + (if (flag) + 0 + else { + when (a) { + A.V1 -> 1 + // JVM: else -> throw + // JVM_IR: else -> {} + } + }) +} + +fun testIfTheElseAnnotated_throwsJvm(a: A, flag: Boolean) { + @Suppress("") + if (flag) + 0 + else { + when (a) { + A.V1 -> 1 + // JVM: else -> throw + // JVM_IR: else -> {} + } + } +} + +fun testLambdaResultExpression_throws(a: A) { + { + when (a) { + A.V1 -> 1 + // else -> throw + } + }() +} + +// JVM_TEMPLATES +// 7 ATHROW + +// JVM_IR_TEMPLATES +// 3 ATHROW \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/when/exhaustiveWhenUnitStatement.kt b/compiler/testData/codegen/bytecodeText/when/exhaustiveWhenUnitStatement.kt index 9f2f9adcc4d..20fec8e5647 100644 --- a/compiler/testData/codegen/bytecodeText/when/exhaustiveWhenUnitStatement.kt +++ b/compiler/testData/codegen/bytecodeText/when/exhaustiveWhenUnitStatement.kt @@ -1,6 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR -// TODO KT-36840 Don't generate 'throw' clause for statement 'when' in JVM_IR enum class AccessMode { READ, WRITE, EXECUTE } diff --git a/compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.fir.txt b/compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.fir.txt new file mode 100644 index 00000000000..2fc6801bd79 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.fir.txt @@ -0,0 +1,222 @@ +FILE fqName: fileName:/exhaustiveWhenElseBranch.kt + CLASS ENUM_CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Enum<.A>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.A + CONSTRUCTOR visibility:private <> () returnType:.A [primary] + BLOCK_BODY + ENUM_CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, ordinal: kotlin.Int) [primary] declared in kotlin.Enum' + : .A + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ENUM_CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Enum<.A>]' + ENUM_ENTRY name:V1 + init: EXPRESSION_BODY + ENUM_CONSTRUCTOR_CALL 'private constructor () [primary] declared in .A' + FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<.A> + SYNTHETIC_BODY kind=ENUM_VALUES + FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:.A + VALUE_PARAMETER name:value index:0 type:kotlin.String + SYNTHETIC_BODY kind=ENUM_VALUEOF + FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Any [fake_override] + overridden: + protected final fun clone (): kotlin.Any declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + FUN FAKE_OVERRIDE name:compareTo visibility:public modality:FINAL <> ($this:kotlin.Enum, other:.A) returnType:kotlin.Int [fake_override,operator] + overridden: + public final fun compareTo (other: E of kotlin.Enum): kotlin.Int [operator] declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + VALUE_PARAMETER name:other index:0 type:.A + FUN FAKE_OVERRIDE name:equals visibility:public modality:FINAL <> ($this:kotlin.Enum, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public final fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Int [fake_override] + overridden: + public final fun hashCode (): kotlin.Int declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Enum) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.String [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.String declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.Int declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + FUN name:testVariableAssignment_throws visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + VAR name:x type:kotlin.Int [val] + BLOCK type=kotlin.Unit origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.A [val] + GET_VAR 'a: .A declared in .testVariableAssignment_throws' type=.A origin=null + 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 tmp_0: .A [val] declared in .testVariableAssignment_throws' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: BLOCK type=kotlin.Unit origin=null + SET_VAR 'val x: kotlin.Int [val] declared in .testVariableAssignment_throws' type=kotlin.Unit origin=EQ + CONST Int type=kotlin.Int value=11 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testStatement_empty visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:.A [val] + GET_VAR 'a: .A declared in .testStatement_empty' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_1: .A [val] declared in .testStatement_empty' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testParenthesized_throwsJvm visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:.A [val] + GET_VAR 'a: .A declared in .testParenthesized_throwsJvm' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_2: .A [val] declared in .testParenthesized_throwsJvm' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testAnnotated_throwsJvm visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:.A [val] + GET_VAR 'a: .A declared in .testAnnotated_throwsJvm' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_3: .A [val] declared in .testAnnotated_throwsJvm' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testExpression_throws visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Int + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testExpression_throws (a: .A): kotlin.Int declared in ' + BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:.A [val] + GET_VAR 'a: .A declared in .testExpression_throws' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_4: .A [val] declared in .testExpression_throws' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testIfTheElseStatement_empty visibility:public modality:FINAL <> (a:.A, flag:kotlin.Boolean) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + VALUE_PARAMETER name:flag index:1 type:kotlin.Boolean + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + WHEN type=kotlin.Int origin=IF + BRANCH + if: GET_VAR 'flag: kotlin.Boolean declared in .testIfTheElseStatement_empty' type=kotlin.Boolean origin=null + then: CONST Int type=kotlin.Int value=0 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:.A [val] + GET_VAR 'a: .A declared in .testIfTheElseStatement_empty' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_5: .A [val] declared in .testIfTheElseStatement_empty' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testIfTheElseParenthesized_throwsJvm visibility:public modality:FINAL <> (a:.A, flag:kotlin.Boolean) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + VALUE_PARAMETER name:flag index:1 type:kotlin.Boolean + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + WHEN type=kotlin.Int origin=IF + BRANCH + if: GET_VAR 'flag: kotlin.Boolean declared in .testIfTheElseParenthesized_throwsJvm' type=kotlin.Boolean origin=null + then: CONST Int type=kotlin.Int value=0 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:.A [val] + GET_VAR 'a: .A declared in .testIfTheElseParenthesized_throwsJvm' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_6: .A [val] declared in .testIfTheElseParenthesized_throwsJvm' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testIfTheElseAnnotated_throwsJvm visibility:public modality:FINAL <> (a:.A, flag:kotlin.Boolean) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + VALUE_PARAMETER name:flag index:1 type:kotlin.Boolean + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + WHEN type=kotlin.Int origin=IF + BRANCH + if: GET_VAR 'flag: kotlin.Boolean declared in .testIfTheElseAnnotated_throwsJvm' type=kotlin.Boolean origin=null + then: CONST Int type=kotlin.Int value=0 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:.A [val] + GET_VAR 'a: .A declared in .testIfTheElseAnnotated_throwsJvm' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_7: .A [val] declared in .testIfTheElseAnnotated_throwsJvm' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testLambdaResultExpression_throws visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Int origin=INVOKE + $this: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.Int declared in .testLambdaResultExpression_throws' + BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:.A [val] + GET_VAR 'a: .A declared in .testLambdaResultExpression_throws' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_8: .A [val] declared in .testLambdaResultExpression_throws.' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null diff --git a/compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.kt b/compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.kt new file mode 100644 index 00000000000..91193189fcb --- /dev/null +++ b/compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.kt @@ -0,0 +1,79 @@ +enum class A { V1 } + +fun testVariableAssignment_throws(a: A) { + val x: Int + when (a) { + A.V1 -> x = 11 + // else -> throw + } +} + +fun testStatement_empty(a: A) { + when (a) { + A.V1 -> 1 + // else -> {} + } +} + +fun testParenthesized_throwsJvm(a: A) { + (when (a) { + A.V1 -> 1 + // JVM: else -> throw, but we don't care + }) +} + +fun testAnnotated_throwsJvm(a: A) { + @Suppress("") when (a) { + A.V1 -> 1 + // JVM: else -> throw, but we don't care + } +} + +fun testExpression_throws(a: A) = + when (a) { + A.V1 -> 1 + // else -> throw + } + +fun testIfTheElseStatement_empty(a: A, flag: Boolean) { + if (flag) + 0 + else { + when (a) { + A.V1 -> 1 + // else -> {} + } + } +} + +fun testIfTheElseParenthesized_throwsJvm(a: A, flag: Boolean) { + (if (flag) + 0 + else { + when (a) { + A.V1 -> 1 + // JVM: else -> throw, but we don't care + } + }) +} + +fun testIfTheElseAnnotated_throwsJvm(a: A, flag: Boolean) { + @Suppress("") + if (flag) + 0 + else { + when (a) { + A.V1 -> 1 + // JVM: else -> throw, but we don't care + } + } +} + +fun testLambdaResultExpression_throws(a: A) { + { + when (a) { + A.V1 -> 1 + // else -> throw + } + }() +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.txt b/compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.txt new file mode 100644 index 00000000000..963aa4b84b2 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.txt @@ -0,0 +1,217 @@ +FILE fqName: fileName:/exhaustiveWhenElseBranch.kt + CLASS ENUM_CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Enum<.A>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.A + CONSTRUCTOR visibility:private <> () returnType:.A [primary] + BLOCK_BODY + ENUM_CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, ordinal: kotlin.Int) [primary] declared in kotlin.Enum' + : .A + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ENUM_CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Enum<.A>]' + ENUM_ENTRY name:V1 + init: EXPRESSION_BODY + ENUM_CONSTRUCTOR_CALL 'private constructor () [primary] declared in .A' + FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum<.A>) returnType:kotlin.Any [fake_override] + overridden: + protected final fun clone (): kotlin.Any declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum<.A> + FUN FAKE_OVERRIDE name:finalize visibility:protected/*protected and package*/ modality:FINAL <> ($this:kotlin.Enum<.A>) returnType:kotlin.Unit [fake_override] + overridden: + protected/*protected and package*/ final fun finalize (): kotlin.Unit declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum<.A> + FUN FAKE_OVERRIDE name:getDeclaringClass visibility:public modality:FINAL <> ($this:kotlin.Enum<.A>) returnType:@[FlexibleNullability] java.lang.Class<@[FlexibleNullability] .A?>? [fake_override] + overridden: + public final fun getDeclaringClass (): @[FlexibleNullability] java.lang.Class<@[FlexibleNullability] E of kotlin.Enum?>? declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum<.A> + FUN FAKE_OVERRIDE name:compareTo visibility:public modality:FINAL <> ($this:kotlin.Enum<.A>, other:.A) returnType:kotlin.Int [fake_override,operator] + overridden: + public final fun compareTo (other: E of kotlin.Enum): kotlin.Int [operator] declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum<.A> + VALUE_PARAMETER name:other index:0 type:.A + FUN FAKE_OVERRIDE name:equals visibility:public modality:FINAL <> ($this:kotlin.Enum<.A>, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public final fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum<.A> + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:FINAL <> ($this:kotlin.Enum<.A>) returnType:kotlin.Int [fake_override] + overridden: + public final fun hashCode (): kotlin.Int declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum<.A> + PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum<.A>) returnType:kotlin.String [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.String declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum<.A> + PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum<.A>) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.Int declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum<.A> + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Enum<.A>) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum<.A> + FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<.A> + SYNTHETIC_BODY kind=ENUM_VALUES + FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:.A + VALUE_PARAMETER name:value index:0 type:kotlin.String + SYNTHETIC_BODY kind=ENUM_VALUEOF + FUN name:testVariableAssignment_throws visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + VAR name:x type:kotlin.Int [val] + BLOCK type=kotlin.Unit origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.A [val] + GET_VAR 'a: .A declared in .testVariableAssignment_throws' type=.A origin=null + 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 tmp_0: .A [val] declared in .testVariableAssignment_throws' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: SET_VAR 'val x: kotlin.Int [val] declared in .testVariableAssignment_throws' type=kotlin.Unit origin=EQ + CONST Int type=kotlin.Int value=11 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testStatement_empty visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + BLOCK type=kotlin.Unit origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:.A [val] + GET_VAR 'a: .A declared in .testStatement_empty' type=.A origin=null + 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 tmp_1: .A [val] declared in .testStatement_empty' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value=1 + FUN name:testParenthesized_throwsJvm visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + BLOCK type=kotlin.Unit origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:.A [val] + GET_VAR 'a: .A declared in .testParenthesized_throwsJvm' type=.A origin=null + 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 tmp_2: .A [val] declared in .testParenthesized_throwsJvm' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value=1 + FUN name:testAnnotated_throwsJvm visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + BLOCK type=kotlin.Unit origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:.A [val] + GET_VAR 'a: .A declared in .testAnnotated_throwsJvm' type=.A origin=null + 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 tmp_3: .A [val] declared in .testAnnotated_throwsJvm' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value=1 + FUN name:testExpression_throws visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Int + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testExpression_throws (a: .A): kotlin.Int declared in ' + BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:.A [val] + GET_VAR 'a: .A declared in .testExpression_throws' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_4: .A [val] declared in .testExpression_throws' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null + FUN name:testIfTheElseStatement_empty visibility:public modality:FINAL <> (a:.A, flag:kotlin.Boolean) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + VALUE_PARAMETER name:flag index:1 type:kotlin.Boolean + BLOCK_BODY + WHEN type=kotlin.Unit origin=IF + BRANCH + if: GET_VAR 'flag: kotlin.Boolean declared in .testIfTheElseStatement_empty' type=kotlin.Boolean origin=null + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value=0 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: BLOCK type=kotlin.Unit origin=null + BLOCK type=kotlin.Unit origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:.A [val] + GET_VAR 'a: .A declared in .testIfTheElseStatement_empty' type=.A origin=null + 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 tmp_5: .A [val] declared in .testIfTheElseStatement_empty' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value=1 + FUN name:testIfTheElseParenthesized_throwsJvm visibility:public modality:FINAL <> (a:.A, flag:kotlin.Boolean) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + VALUE_PARAMETER name:flag index:1 type:kotlin.Boolean + BLOCK_BODY + WHEN type=kotlin.Unit origin=IF + BRANCH + if: GET_VAR 'flag: kotlin.Boolean declared in .testIfTheElseParenthesized_throwsJvm' type=kotlin.Boolean origin=null + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value=0 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: BLOCK type=kotlin.Unit origin=null + BLOCK type=kotlin.Unit origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:.A [val] + GET_VAR 'a: .A declared in .testIfTheElseParenthesized_throwsJvm' type=.A origin=null + 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 tmp_6: .A [val] declared in .testIfTheElseParenthesized_throwsJvm' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value=1 + FUN name:testIfTheElseAnnotated_throwsJvm visibility:public modality:FINAL <> (a:.A, flag:kotlin.Boolean) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + VALUE_PARAMETER name:flag index:1 type:kotlin.Boolean + BLOCK_BODY + WHEN type=kotlin.Unit origin=IF + BRANCH + if: GET_VAR 'flag: kotlin.Boolean declared in .testIfTheElseAnnotated_throwsJvm' type=kotlin.Boolean origin=null + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value=0 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: BLOCK type=kotlin.Unit origin=null + BLOCK type=kotlin.Unit origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:.A [val] + GET_VAR 'a: .A declared in .testIfTheElseAnnotated_throwsJvm' type=.A origin=null + 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 tmp_7: .A [val] declared in .testIfTheElseAnnotated_throwsJvm' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value=1 + FUN name:testLambdaResultExpression_throws visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:.A + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Int origin=INVOKE + $this: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.Int declared in .testLambdaResultExpression_throws' + BLOCK type=kotlin.Int origin=WHEN + VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:.A [val] + GET_VAR 'a: .A declared in .testLambdaResultExpression_throws' type=.A origin=null + WHEN type=kotlin.Int 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 tmp_8: .A [val] declared in .testLambdaResultExpression_throws.' type=.A origin=null + arg1: GET_ENUM 'ENUM_ENTRY name:V1' type=.A + then: CONST Int type=kotlin.Int value=1 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun noWhenBranchMatchedException (): kotlin.Nothing declared in kotlin.internal.ir' type=kotlin.Nothing origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 01598ff6836..fd5d59cf89b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -4820,6 +4820,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/when/exhaustiveWhenReturn.kt"); } + @TestMetadata("exhaustiveWhenSpecialCases.kt") + public void testExhaustiveWhenSpecialCases() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/when/exhaustiveWhenSpecialCases.kt"); + } + @TestMetadata("exhaustiveWhenUnit.kt") public void testExhaustiveWhenUnit() throws Exception { runTest("compiler/testData/codegen/bytecodeText/when/exhaustiveWhenUnit.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index ecaa700580a..4bb2ca1297b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -4748,6 +4748,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/when/exhaustiveWhenReturn.kt"); } + @TestMetadata("exhaustiveWhenSpecialCases.kt") + public void testExhaustiveWhenSpecialCases() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/when/exhaustiveWhenSpecialCases.kt"); + } + @TestMetadata("exhaustiveWhenUnit.kt") public void testExhaustiveWhenUnit() throws Exception { runTest("compiler/testData/codegen/bytecodeText/when/exhaustiveWhenUnit.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 5fc7af29e50..cb862131311 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -916,6 +916,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/expressions/equals.kt"); } + @TestMetadata("exhaustiveWhenElseBranch.kt") + public void testExhaustiveWhenElseBranch() throws Exception { + runTest("compiler/testData/ir/irText/expressions/exhaustiveWhenElseBranch.kt"); + } + @TestMetadata("extFunInvokeAsFun.kt") public void testExtFunInvokeAsFun() throws Exception { runTest("compiler/testData/ir/irText/expressions/extFunInvokeAsFun.kt");