From 50116fd8fc9bf472e8db1c2fa1dccfe208a21979 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Mon, 7 May 2018 14:52:58 +0300 Subject: [PATCH] Fix coercion result for inline classes, add comment --- .../org/jetbrains/kotlin/codegen/StackValue.java | 16 +++++++++++++++- .../inlineClasses/isCheckForInlineClass.kt | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index 16afc8bc0a1..196328b25ae 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -454,28 +454,42 @@ public abstract class StackValue { if (fromKotlinType.equals(toKotlinType) && fromType.equals(toType)) return true; + /* + * Preconditions: one of the types is definitely inline class type and types are not equal + * Consider the following situations: + * - both types are inline class types: we do box/unbox only if they are not both boxed or unboxed + * - from type is inline class type: we should do box, because target type can be only "subtype" of inline class type (like Any) + * - target type is inline class type: we should do unbox, because from type can come from some 'is' check for object type + * + * "return true" means that types were coerced successfully and usual coercion shouldn't be evaluated + * */ + if (isFromTypeInlineClass && isToTypeInlineClass) { boolean isFromTypeUnboxed = isUnboxedInlineClass(fromKotlinType, fromType); boolean isToTypeUnboxed = isUnboxedInlineClass(toKotlinType, toType); if (isFromTypeUnboxed && !isToTypeUnboxed) { boxInlineClass(fromKotlinType, v); + return true; } else if (!isFromTypeUnboxed && isToTypeUnboxed) { unboxInlineClass(fromType, toKotlinType, v); + return true; } } else if (isFromTypeInlineClass) { if (isUnboxedInlineClass(fromKotlinType, fromType)) { boxInlineClass(fromKotlinType, v); + return true; } } else { // isToTypeInlineClass is `true` if (isUnboxedInlineClass(toKotlinType, toType)) { unboxInlineClass(fromType, toKotlinType, v); + return true; } } - return true; + return false; } private static boolean isUnboxedInlineClass(@NotNull KotlinType kotlinType, @NotNull Type actualType) { diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/isCheckForInlineClass.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/isCheckForInlineClass.kt index 3b632a906f3..005c4ae2bb9 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/isCheckForInlineClass.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/isCheckForInlineClass.kt @@ -17,7 +17,7 @@ fun test(a: Any, b: Any?) { } // 2 INSTANCEOF UInt -// 1 CHECKCAST UInt +// 2 CHECKCAST UInt // 1 INVOKEVIRTUAL UInt.unbox // 2 INVOKESTATIC UInt\$Erased.member