From 396cc7d02b9b43779815880d626ba3c8bcbe48c1 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 7 Feb 2018 06:11:15 +0300 Subject: [PATCH] Support unboxing of inline classes in elvis --- .../kotlin/codegen/ExpressionCodegen.java | 14 +++++++++++--- .../useInlineClassesInsideElvisOperator.kt | 19 +++++++++++++++++++ .../unboxInlineClassAfterElvis.kt | 14 ++++++++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/BytecodeTextTestGenerated.java | 6 ++++++ .../LightAnalysisModeTestGenerated.java | 6 ++++++ .../semantics/JsCodegenBoxTestGenerated.java | 6 ++++++ 8 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/box/inlineClasses/useInlineClassesInsideElvisOperator.kt create mode 100644 compiler/testData/codegen/bytecodeText/inlineClasses/unboxInlineClassAfterElvis.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 7fa038894f7..77f6e6aae6d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -342,7 +342,12 @@ public class ExpressionCodegen extends KtVisitor impleme } } - value.put(type, null, v); + KotlinType ktType = null; + if (expr instanceof KtExpression) { + ktType = kotlinType((KtExpression) expr); + } + + value.put(type, ktType, v); } @NotNull @@ -3358,7 +3363,10 @@ public class ExpressionCodegen extends KtVisitor impleme KtExpression left = expression.getLeft(); Type exprType = expressionType(expression); + KotlinType exprKotlinType = kotlinType(expression); + Type leftType = expressionType(left); + KotlinType leftKotlinType = kotlinType(left); Label ifNull = new Label(); @@ -3369,12 +3377,12 @@ public class ExpressionCodegen extends KtVisitor impleme return value; } - return StackValue.operation(exprType, v -> { + return StackValue.operation(exprType, exprKotlinType, v -> { value.put(value.type, value.kotlinType, v); v.dup(); v.ifnull(ifNull); - StackValue.onStack(leftType).put(exprType, null, v); + StackValue.onStack(leftType, leftKotlinType).put(exprType, exprKotlinType, v); Label end = new Label(); v.goTo(end); diff --git a/compiler/testData/codegen/box/inlineClasses/useInlineClassesInsideElvisOperator.kt b/compiler/testData/codegen/box/inlineClasses/useInlineClassesInsideElvisOperator.kt new file mode 100644 index 00000000000..5dab07739c3 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/useInlineClassesInsideElvisOperator.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +InlineClasses + +inline class UInt(private val u: Int) { + fun asResult() = u +} + +fun test(x1: UInt?, x2: UInt?, y: UInt, z: UInt?): Int { + val a = x1 ?: y + val b = x1 ?: z!! + val c = x1 ?: x2 ?: y + return a.asResult() + b.asResult() + c.asResult() +} + +fun box(): String { + val u1 = UInt(10) + val u2 = UInt(20) + val r = test(null, null, u1, u2) + return if (r != 40) "fail: $r" else "OK" +} diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/unboxInlineClassAfterElvis.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/unboxInlineClassAfterElvis.kt new file mode 100644 index 00000000000..7ac92925988 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/unboxInlineClassAfterElvis.kt @@ -0,0 +1,14 @@ +// !LANGUAGE: +InlineClasses + +inline class UInt(private val u: Int) + +fun test(x: UInt?, y: UInt) { + val a = x ?: y // unbox + val b = x ?: x!! // unbox unbox +} + +// 0 INVOKESTATIC UInt\$Erased.box +// 3 INVOKEVIRTUAL UInt.unbox + +// 0 valueOf +// 0 intValue \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 33bb5ce3e82..741bcec1eb7 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -10359,6 +10359,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("useInlineClassesInsideElvisOperator.kt") + public void testUseInlineClassesInsideElvisOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/useInlineClassesInsideElvisOperator.kt"); + doTest(fileName); + } + @TestMetadata("useInlineFunctionInsideInlineClass.kt") public void testUseInlineFunctionInsideInlineClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/useInlineFunctionInsideInlineClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index f7578525ae7..0820c5c8d15 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -10359,6 +10359,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("useInlineClassesInsideElvisOperator.kt") + public void testUseInlineClassesInsideElvisOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/useInlineClassesInsideElvisOperator.kt"); + doTest(fileName); + } + @TestMetadata("useInlineFunctionInsideInlineClass.kt") public void testUseInlineFunctionInsideInlineClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/useInlineFunctionInsideInlineClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 6125147a4c5..cf25dc59ccd 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -1962,6 +1962,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } + @TestMetadata("unboxInlineClassAfterElvis.kt") + public void testUnboxInlineClassAfterElvis() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/unboxInlineClassAfterElvis.kt"); + doTest(fileName); + } + @TestMetadata("unboxInlineClassAfterSafeCall.kt") public void testUnboxInlineClassAfterSafeCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/unboxInlineClassAfterSafeCall.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 1663a619e76..356113daf6f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -10359,6 +10359,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("useInlineClassesInsideElvisOperator.kt") + public void testUseInlineClassesInsideElvisOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/useInlineClassesInsideElvisOperator.kt"); + doTest(fileName); + } + @TestMetadata("useInlineFunctionInsideInlineClass.kt") public void testUseInlineFunctionInsideInlineClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/useInlineFunctionInsideInlineClass.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index e6ae0744afe..49f6b8cf5d5 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -11319,6 +11319,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("useInlineClassesInsideElvisOperator.kt") + public void testUseInlineClassesInsideElvisOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/useInlineClassesInsideElvisOperator.kt"); + doTest(fileName); + } + @TestMetadata("useInlineFunctionInsideInlineClass.kt") public void testUseInlineFunctionInsideInlineClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/useInlineFunctionInsideInlineClass.kt");