From d0134f2c64d290fad7e7831fbd0a30358d994b5a Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 27 Feb 2017 16:21:16 +0300 Subject: [PATCH] KT-16437 Incorrect type inference for some when coerced to Unit If the result of 'when' is not used in an expression, this 'when' expression has type 'Unit' despite of whatever FE has inferred. --- .../generators/BranchingExpressionGenerator.kt | 7 ++++++- compiler/testData/ir/irCfg/when/whenReturn.txt | 2 +- .../ir/irText/expressions/whenCoercedToUnit.kt | 7 +++++++ .../ir/irText/expressions/whenCoercedToUnit.txt | 13 +++++++++++++ .../testData/ir/irText/expressions/whenReturn.txt | 4 ++-- .../kotlin/ir/IrTextTestCaseGenerated.java | 6 ++++++ 6 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/ir/irText/expressions/whenCoercedToUnit.kt create mode 100644 compiler/testData/ir/irText/expressions/whenCoercedToUnit.txt 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 69306103819..498c39f7399 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 @@ -85,7 +85,12 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta scope.createTemporaryVariable(statementGenerator.generateExpression(it), "subject") } - val resultType = getInferredTypeWithImplicitCastsOrFail(expression) + // TODO relies on ControlFlowInformationProvider, get rid of it + val resultType = + if (context.bindingContext[BindingContext.USED_AS_EXPRESSION, expression] ?: false) + getInferredTypeWithImplicitCastsOrFail(expression) + else + context.builtIns.unitType val irWhen = IrWhenImpl(expression.startOffset, expression.endOffset, resultType, IrStatementOrigin.WHEN) diff --git a/compiler/testData/ir/irCfg/when/whenReturn.txt b/compiler/testData/ir/irCfg/when/whenReturn.txt index 078317f60fc..445747384d5 100644 --- a/compiler/testData/ir/irCfg/when/whenReturn.txt +++ b/compiler/testData/ir/irCfg/when/whenReturn.txt @@ -5,7 +5,7 @@ CONTENT 1 FUN public fun toString(grade: kotlin.String): kotlin.String 2 GET_VAR 'value-parameter grade: String' type=kotlin.String origin=null 3 VAR IR_TEMPORARY_VARIABLE val tmp0_subject: kotlin.String - 4 WHEN type=kotlin.Nothing origin=WHEN + 4 WHEN type=kotlin.Unit origin=WHEN 5 GET_VAR 'tmp0_subject: String' type=kotlin.String origin=null 6 CONST String type=kotlin.String value='A' OUTGOING -> BB 1, 5 diff --git a/compiler/testData/ir/irText/expressions/whenCoercedToUnit.kt b/compiler/testData/ir/irText/expressions/whenCoercedToUnit.kt new file mode 100644 index 00000000000..cfbd1828b35 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/whenCoercedToUnit.kt @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +fun foo(x: Int) { + when (x) { + 0 -> 0 + } +} diff --git a/compiler/testData/ir/irText/expressions/whenCoercedToUnit.txt b/compiler/testData/ir/irText/expressions/whenCoercedToUnit.txt new file mode 100644 index 00000000000..bb01f0a90a5 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/whenCoercedToUnit.txt @@ -0,0 +1,13 @@ +FILE /whenCoercedToUnit.kt + FUN public fun foo(x: kotlin.Int): kotlin.Unit + BLOCK_BODY + BLOCK type=kotlin.Unit origin=WHEN + VAR IR_TEMPORARY_VARIABLE val tmp0_subject: kotlin.Int + GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=null + WHEN type=kotlin.Unit origin=WHEN + BRANCH + if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'tmp0_subject: Int' type=kotlin.Int origin=null + arg1: CONST Int type=kotlin.Int value='0' + then: TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value='0' diff --git a/compiler/testData/ir/irText/expressions/whenReturn.txt b/compiler/testData/ir/irText/expressions/whenReturn.txt index eca3f4385bd..ec99536bc7c 100644 --- a/compiler/testData/ir/irText/expressions/whenReturn.txt +++ b/compiler/testData/ir/irText/expressions/whenReturn.txt @@ -1,10 +1,10 @@ FILE /whenReturn.kt FUN public fun toString(grade: kotlin.String): kotlin.String BLOCK_BODY - BLOCK type=kotlin.Nothing origin=WHEN + BLOCK type=kotlin.Unit origin=WHEN VAR IR_TEMPORARY_VARIABLE val tmp0_subject: kotlin.String GET_VAR 'value-parameter grade: String' type=kotlin.String origin=null - WHEN type=kotlin.Nothing origin=WHEN + WHEN type=kotlin.Unit origin=WHEN BRANCH if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ arg0: GET_VAR 'tmp0_subject: String' type=kotlin.String origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 750c242919c..1a627499c94 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -689,6 +689,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("whenCoercedToUnit.kt") + public void testWhenCoercedToUnit() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/whenCoercedToUnit.kt"); + doTest(fileName); + } + @TestMetadata("whenElse.kt") public void testWhenElse() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/whenElse.kt");