From 048e96ef6a118975e7ba63c851d1d2497b1caf2d Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 20 Nov 2015 18:59:12 +0300 Subject: [PATCH] Fix safe call code generation for ranges. --- .../org/jetbrains/kotlin/codegen/Callable.kt | 3 +-- .../kotlin/codegen/ExpressionCodegen.java | 4 +-- .../kotlin/codegen/intrinsics/RangeTo.kt | 15 ++++++++--- .../boxWithStdlib/ranges/safeCallRangeTo.kt | 26 +++++++++++++++++++ ...lackBoxWithStdlibCodegenTestGenerated.java | 6 +++++ 5 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/ranges/safeCallRangeTo.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/Callable.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/Callable.kt index 5aed03a2c2b..3a5a3c48b88 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/Callable.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/Callable.kt @@ -45,8 +45,7 @@ public interface Callable { } } - public fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) { - + public fun afterReceiverGeneration(v: InstructionAdapter) { } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index d9717128965..19fe3036eb8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -27,7 +27,6 @@ import com.intellij.util.containers.Stack; import kotlin.CollectionsKt; import kotlin.Unit; import kotlin.jvm.functions.Function1; -import kotlin.jvm.functions.Function2; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.CodegenUtil; @@ -2394,11 +2393,10 @@ public class ExpressionCodegen extends KtVisitor impleme @NotNull CallGenerator callGenerator, @NotNull ArgumentGenerator argumentGenerator ) { - callableMethod.beforeParameterGeneration(v, null); - if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); receiver.put(receiver.type, v); + callableMethod.afterReceiverGeneration(v); } callGenerator.putHiddenParams(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt index f8091021d92..8c900a29558 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt @@ -44,10 +44,19 @@ public class RangeTo : IntrinsicMethod() { nullOr(method.dispatchReceiverType, argType), nullOr(method.extensionReceiverType, argType) ) { - override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) { + override fun afterReceiverGeneration(v: InstructionAdapter) { v.anew(returnType) - v.dup() - value?.moveToTopOfStack(value.type, v, 2) + when (argType.size) { + 1 -> { + v.dupX1() + v.swap() + } + 2 -> { + v.dup() + v.dup2X2() + v.pop2() + } + } } override fun invokeIntrinsic(v: InstructionAdapter) { diff --git a/compiler/testData/codegen/boxWithStdlib/ranges/safeCallRangeTo.kt b/compiler/testData/codegen/boxWithStdlib/ranges/safeCallRangeTo.kt new file mode 100644 index 00000000000..bcb5397fa92 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/ranges/safeCallRangeTo.kt @@ -0,0 +1,26 @@ +fun charRange(x: Char?, y: Char) = x?.rangeTo(y) +fun byteRange(x: Byte?, y: Byte) = x?.rangeTo(y) +fun shortRange(x: Short?, y: Short) = x?.rangeTo(y) +fun intRange(x: Int?, y: Int) = x?.rangeTo(y) +fun longRange(x: Long?, y: Long) = x?.rangeTo(y) +fun floatRange(x: Float?, y: Float) = x?.rangeTo(y) +fun dougleRange(x: Double?, y: Double) = x?.rangeTo(y) + +inline fun testSafeRange(x: T, y: T, expectStr: String, safeRange: (T?, T) -> R?) { + val rNull = safeRange(null, y) + assert (rNull == null) { "${T::class.simpleName}: Expected: null, got $rNull" } + + val rxy = safeRange(x, y) + assert (rxy?.toString() == expectStr) { "${T::class.simpleName}: Expected: $expectStr, got $rxy" } +} + +fun box(): String { + testSafeRange('0', '1', "0..1", ::charRange) + testSafeRange(0, 1, "0..1", ::byteRange) + testSafeRange(0, 1, "0..1", ::shortRange) + testSafeRange(0, 1, "0..1", ::intRange) + testSafeRange(0L, 1L, "0..1", ::longRange) + testSafeRange(0.0f, 1.0f, "0.0..1.0", ::floatRange) + testSafeRange(0.0, 1.0, "0.0..1.0", ::dougleRange) + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 9c607fdd272..712aaef1913 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -2707,6 +2707,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("safeCallRangeTo.kt") + public void testSafeCallRangeTo() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/ranges/safeCallRangeTo.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("compiler/testData/codegen/boxWithStdlib/ranges/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)