From 05768511022b38dfb5a87251e2388aa533ac68f6 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 11 Dec 2013 17:56:10 +0400 Subject: [PATCH] Fix codegen for closures returning 'Unit?' Only do a checkcast when we need to coerce Object to Unit: the code was hopefully type-checked so that it'll only be necessary when the value is either Unit.VALUE or null --- .../src/org/jetbrains/jet/codegen/StackValue.java | 5 ++++- .../codegen/box/unit/closureReturnsNullableUnit.kt | 8 ++++++++ .../testData/codegen/box/unit/nullableUnitInWhen3.kt | 12 ++++++++++++ .../generated/BlackBoxCodegenTestGenerated.java | 10 ++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/box/unit/closureReturnsNullableUnit.kt create mode 100644 compiler/testData/codegen/box/unit/nullableUnitInWhen3.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index c6597d3155a..1b5cf7816cb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -242,7 +242,10 @@ public abstract class StackValue { } } else if (toType.equals(JET_UNIT_TYPE)) { - if (!fromType.equals(getType(Void.class))) { + if (fromType.equals(getType(Object.class))) { + v.checkcast(JET_UNIT_TYPE); + } + else if (!fromType.equals(getType(Void.class))) { pop(v, fromType); putUnitInstance(v); } diff --git a/compiler/testData/codegen/box/unit/closureReturnsNullableUnit.kt b/compiler/testData/codegen/box/unit/closureReturnsNullableUnit.kt new file mode 100644 index 00000000000..604b35ab71f --- /dev/null +++ b/compiler/testData/codegen/box/unit/closureReturnsNullableUnit.kt @@ -0,0 +1,8 @@ +fun isNull(x: Unit?) = x == null + +fun box(): String { + val closure: () -> Unit? = { null } + if (!isNull(closure())) return "Fail 1" + + return "OK" +} diff --git a/compiler/testData/codegen/box/unit/nullableUnitInWhen3.kt b/compiler/testData/codegen/box/unit/nullableUnitInWhen3.kt new file mode 100644 index 00000000000..b2e2b0ae439 --- /dev/null +++ b/compiler/testData/codegen/box/unit/nullableUnitInWhen3.kt @@ -0,0 +1,12 @@ +fun foo() {} + +fun box(): String { + val x = when ("A") { + "B" -> foo() + else -> null + } + + foo() + + return if (x == null) "OK" else "Fail" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 8fe7c9c93c1..e479d72785f 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -4868,6 +4868,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/unit"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("closureReturnsNullableUnit.kt") + public void testClosureReturnsNullableUnit() throws Exception { + doTest("compiler/testData/codegen/box/unit/closureReturnsNullableUnit.kt"); + } + @TestMetadata("kt3634.kt") public void testKt3634() throws Exception { doTest("compiler/testData/codegen/box/unit/kt3634.kt"); @@ -4898,6 +4903,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/unit/nullableUnitInWhen2.kt"); } + @TestMetadata("nullableUnitInWhen3.kt") + public void testNullableUnitInWhen3() throws Exception { + doTest("compiler/testData/codegen/box/unit/nullableUnitInWhen3.kt"); + } + @TestMetadata("unitClassObject.kt") public void testUnitClassObject() throws Exception { doTest("compiler/testData/codegen/box/unit/unitClassObject.kt");