Fix coercion result for inline classes, add comment
This commit is contained in:
@@ -454,28 +454,42 @@ public abstract class StackValue {
|
|||||||
|
|
||||||
if (fromKotlinType.equals(toKotlinType) && fromType.equals(toType)) return true;
|
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) {
|
if (isFromTypeInlineClass && isToTypeInlineClass) {
|
||||||
boolean isFromTypeUnboxed = isUnboxedInlineClass(fromKotlinType, fromType);
|
boolean isFromTypeUnboxed = isUnboxedInlineClass(fromKotlinType, fromType);
|
||||||
boolean isToTypeUnboxed = isUnboxedInlineClass(toKotlinType, toType);
|
boolean isToTypeUnboxed = isUnboxedInlineClass(toKotlinType, toType);
|
||||||
if (isFromTypeUnboxed && !isToTypeUnboxed) {
|
if (isFromTypeUnboxed && !isToTypeUnboxed) {
|
||||||
boxInlineClass(fromKotlinType, v);
|
boxInlineClass(fromKotlinType, v);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if (!isFromTypeUnboxed && isToTypeUnboxed) {
|
else if (!isFromTypeUnboxed && isToTypeUnboxed) {
|
||||||
unboxInlineClass(fromType, toKotlinType, v);
|
unboxInlineClass(fromType, toKotlinType, v);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isFromTypeInlineClass) {
|
else if (isFromTypeInlineClass) {
|
||||||
if (isUnboxedInlineClass(fromKotlinType, fromType)) {
|
if (isUnboxedInlineClass(fromKotlinType, fromType)) {
|
||||||
boxInlineClass(fromKotlinType, v);
|
boxInlineClass(fromKotlinType, v);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // isToTypeInlineClass is `true`
|
else { // isToTypeInlineClass is `true`
|
||||||
if (isUnboxedInlineClass(toKotlinType, toType)) {
|
if (isUnboxedInlineClass(toKotlinType, toType)) {
|
||||||
unboxInlineClass(fromType, toKotlinType, v);
|
unboxInlineClass(fromType, toKotlinType, v);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isUnboxedInlineClass(@NotNull KotlinType kotlinType, @NotNull Type actualType) {
|
private static boolean isUnboxedInlineClass(@NotNull KotlinType kotlinType, @NotNull Type actualType) {
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ fun test(a: Any, b: Any?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2 INSTANCEOF UInt
|
// 2 INSTANCEOF UInt
|
||||||
// 1 CHECKCAST UInt
|
// 2 CHECKCAST UInt
|
||||||
|
|
||||||
// 1 INVOKEVIRTUAL UInt.unbox
|
// 1 INVOKEVIRTUAL UInt.unbox
|
||||||
// 2 INVOKESTATIC UInt\$Erased.member
|
// 2 INVOKESTATIC UInt\$Erased.member
|
||||||
|
|||||||
Reference in New Issue
Block a user