Generate function from Any for inline classes same as for data classes

#KT-24873 Fixed
 #KT-25293 Fixed
 #KT-25299 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2018-08-06 00:55:23 +03:00
parent 043ce1cb27
commit 6d4d244c28
37 changed files with 336 additions and 43 deletions
@@ -0,0 +1,51 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR, JS_IR, JS
inline class Foo(val x: Int)
inline class FooRef(val y: String)
inline class FooLong(val x: Long)
inline class FooDouble(val y: Double)
fun box(): String {
val f = Foo(42)
if (f.toString() != "Foo(x=42)") return "Fail 1: $f"
if (!f.equals(f)) return "Fail 2"
val g = Foo(43)
if (f.equals(g)) return "Fail 3"
if (42.hashCode() != f.hashCode()) return "Fail 4"
val fRef = FooRef("42")
if (fRef.toString() != "FooRef(y=42)") return "Fail 5: $fRef"
if (!fRef.equals(fRef)) return "Fail 6"
val gRef = FooRef("43")
if (fRef.equals(gRef)) return "Fail 7"
if ("42".hashCode() != fRef.hashCode()) return "Fail 8"
val fLong = FooLong(42)
if (fLong.toString() != "FooLong(x=42)") return "Fail 9: $fLong"
if (!fLong.equals(fLong)) return "Fail 10"
val gLong = FooLong(43)
if (fLong.equals(gLong)) return "Fail 11"
if (42L.hashCode() != fLong.hashCode()) return "Fail 12"
val fDouble = FooDouble(42.0)
if (fDouble.toString() != "FooDouble(y=42.0)") return "Fail 13: $fDouble"
if (!fDouble.equals(fDouble)) return "Fail 14"
val gDouble = FooDouble(43.0)
if (fDouble.equals(gDouble)) return "Fail 15"
if (42.0.hashCode() != fDouble.hashCode()) return "Fail 16"
return "OK"
}
@@ -10,7 +10,10 @@ public final class Foo$Companion {
public final static class Foo$Erased {
public final static @org.jetbrains.annotations.NotNull method box(p0: int): Foo
public static method constructor(p0: int): int
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
public static method hashCode(p0: int): int
public final static method inInlineClass(p0: int): void
public static @org.jetbrains.annotations.NotNull method toString(p0: int): java.lang.String
}
@kotlin.Metadata
@@ -21,7 +24,10 @@ public final class Foo {
inner class Foo$Companion
static method <clinit>(): void
public method <init>(p0: int): void
public method equals(p0: java.lang.Object): boolean
public final method getX(): int
public method hashCode(): int
public final method inInlineClass(): void
public method toString(): java.lang.String
public final method unbox(): int
}
@@ -2,16 +2,22 @@
public final static class Foo$Erased {
public final static @org.jetbrains.annotations.NotNull method box(p0: int): Foo
public static method constructor(p0: int): int
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
public final static method getAsThis(p0: int): int
public final static method getProp(p0: int): int
public static method hashCode(p0: int): int
public static @org.jetbrains.annotations.NotNull method toString(p0: int): java.lang.String
}
@kotlin.Metadata
public final class Foo {
private final field x: int
public method <init>(p0: int): void
public method equals(p0: java.lang.Object): boolean
public final method getAsThis(): int
public final method getProp(): int
public final method getX(): int
public method hashCode(): int
public method toString(): java.lang.String
public final method unbox(): int
}
@@ -7,15 +7,21 @@ public interface A {
public final static class Foo$Erased {
public final static @org.jetbrains.annotations.NotNull method box(p0: long): Foo
public static method constructor(p0: long): long
public static method equals(p0: long, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
public static method foo(p0: long, p1: long): void
public static method hashCode(p0: long): int
public static @org.jetbrains.annotations.NotNull method toString(p0: long): java.lang.String
}
@kotlin.Metadata
public final class Foo {
private final field x: long
public method <init>(p0: long): void
public method equals(p0: java.lang.Object): boolean
public synthetic method foo(p0: java.lang.Object): void
public method foo(p0: long): void
public final method getX(): long
public method hashCode(): int
public method toString(): java.lang.String
public final method unbox(): long
}
@@ -3,8 +3,11 @@ public final static class Foo$Erased {
public final static @org.jetbrains.annotations.NotNull method box(p0: long): Foo
public static method constructor(p0: long): long
public final static method empty(p0: long): void
public static method equals(p0: long, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
public final static method extension(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.Object, @org.jetbrains.annotations.NotNull p2: java.lang.String): void
public static method hashCode(p0: long): int
public final static method param(p0: long, p1: double): void
public static @org.jetbrains.annotations.NotNull method toString(p0: long): java.lang.String
}
@kotlin.Metadata
@@ -12,8 +15,11 @@ public final class Foo {
private final field l: long
public method <init>(p0: long): void
public final method empty(): void
public method equals(p0: java.lang.Object): boolean
public final method extension(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.lang.String): void
public final method getL(): long
public method hashCode(): int
public final method param(p0: double): void
public method toString(): java.lang.String
public final method unbox(): long
}
@@ -1,7 +1,11 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(val u: Int)
// FILE: test.kt
fun test(a1: Any, a2: UInt?, a3: Any?, a4: Any?) {
val b1 = a1 as UInt // checkcast, unbox
val b2 = a2 as UInt // unbox
@@ -9,6 +13,7 @@ fun test(a1: Any, a2: UInt?, a3: Any?, a4: Any?) {
val b4 = a4 as? UInt // instanceof, checkcast
}
// @TestKt.class:
// 3 CHECKCAST UInt
// 2 INVOKEVIRTUAL UInt.unbox
@@ -1,13 +1,17 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(private val data: Int)
// FILE: test.kt
fun f() {
val unull = UInt(1) ?: null
}
// @TestKt.class:
// 0 INVOKESTATIC UInt\$Erased.box
// 0 INVOKEVIRTUAL UInt.unbox
// 0 valueOf
// 0 intValue
@@ -1,17 +1,21 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(val u: Int)
fun <T> takeVarargs(vararg e: T) {}
// FILE: test.kt
fun test(u1: UInt, u2: UInt, u3: UInt?) {
takeVarargs(u1, u2) // 2 box
takeVarargs(u3)
takeVarargs(u1, u3) // box
}
// @TestKt.class:
// 3 INVOKESTATIC UInt\$Erased.box
// 0 INVOKEVIRTUAL UInt.unbox
// 0 valueOf
// 0 intValue
@@ -1,8 +1,12 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class AsInt(val value: Int)
inline class AsAny(val value: Any)
// FILE: test.kt
fun takeAny(a: Any) {}
fun test() {
@@ -10,6 +14,7 @@ fun test() {
takeAny(AsAny(123)) // box int, box inline class
}
// @TestKt.class:
// 1 INVOKESTATIC AsInt\$Erased.box
// 0 INVOKEVIRTUAL AsInt.unbox
@@ -1,7 +1,11 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class Result<T>(val a: Any?)
// FILE: test.kt
fun test() {
val a = Result<Int>(1) // valueOf
val b = Result<String>("sample")
@@ -10,6 +14,7 @@ fun test() {
val d = Result<Result<Int>>(Result<Int>(1)) // valueOf
}
// @TestKt.class:
// 0 INVOKESTATIC Result\$Erased.box
// 0 INVOKEVIRTUAL Result.unbox
@@ -1,5 +1,7 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class Foo(val a: Int) {
fun member(): String = ""
}
@@ -9,6 +11,7 @@ fun <T> T.idExtension(): T = this
fun Foo.extension() {}
// FILE: test.kt
fun test(f: Foo) {
id(f) // box
@@ -21,8 +24,8 @@ fun test(f: Foo) {
val b = id(f).idExtension() // box unbox
}
// @TestKt.class:
// 6 INVOKESTATIC Foo\$Erased.box
// 4 INVOKEVIRTUAL Foo.unbox
// 0 valueOf
// 0 intValue
@@ -1,7 +1,11 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(private val u: Int)
// FILE: test.kt
fun test(x: UInt?, y: UInt) {
val a = run {
x!!
@@ -12,6 +16,7 @@ fun test(x: UInt?, y: UInt) {
}
}
// @TestKt.class:
// 0 INVOKESTATIC UInt\$Erased.box
// 1 INVOKEVIRTUAL UInt.unbox
@@ -16,11 +16,12 @@ fun test() {
} // unbox ULong
}
// @TestKt.class:
// 1 INVOKESTATIC UInt\$Erased.box
// 1 INVOKEVIRTUAL UInt.unbox
// 2 INVOKEVIRTUAL UInt.unbox
// 1 INVOKESTATIC ULong\$Erased.box
// 1 INVOKEVIRTUAL ULong.unbox
// 2 INVOKEVIRTUAL ULong.unbox
// 0 valueOf
// 0 intValue
@@ -1,7 +1,11 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class Foo(val a: Int)
// FILE: test.kt
fun <T> id(x: T): T = x
inline fun <T> inlinedId(x: T): T = x
@@ -18,8 +22,8 @@ fun test(f: Foo) {
val b = inlinedId(f).inlinedIdExtension()
}
// @TestKt.class:
// 2 INVOKESTATIC Foo\$Erased.box
// 1 INVOKEVIRTUAL Foo.unbox
// 0 valueOf
// 0 intValue
@@ -1,7 +1,11 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class ULong(val l: Long)
// FILE: test.kt
fun nonLocal(): ULong? {
val u = ULong(0)
@@ -22,6 +26,7 @@ fun labeled(): ULong? {
}
}
// @TestKt.class:
// 2 INVOKESTATIC ULong\$Erased.box
// 0 INVOKEVIRTUAL ULong.unbox
@@ -15,4 +15,4 @@ inline class Foo(val x: Int) {
// 2 INVOKESTATIC Foo\$Erased.empty \(I\)V
// 2 INVOKESTATIC Foo\$Erased.withParam \(ILjava/lang/String;\)V
// 2 INVOKESTATIC Foo\$Erased.withInlineClassParam \(II\)V
// 0 INVOKEVIRTUAL
// 5 INVOKEVIRTUAL
@@ -1,7 +1,11 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(val value: Int)
// FILE: test.kt
fun test(x: UInt?) {
x?.myLet { // unbox
takeUInt(it)
@@ -24,6 +28,7 @@ fun takeNullableUInt(y: UInt?) {}
inline fun <T> T.myLet(f: (T) -> Unit) = f(this)
// @TestKt.class:
// 1 INVOKESTATIC UInt\$Erased.box
// 5 INVOKEVIRTUAL UInt.unbox
@@ -1,5 +1,7 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class WithPrimitive(val a: Int)
fun takeWithPrimitive(a: WithPrimitive) {}
@@ -9,6 +11,8 @@ fun takeWithReference(a: WithReference) {}
inline class WithNullableReference(val a: Any?)
fun takeWithNullableReference(a: WithNullableReference) {}
// FILE: test.kt
fun foo(a: WithPrimitive?, b: WithPrimitive) {
takeWithPrimitive(a!!) // unbox
takeWithPrimitive(a) // unbox
@@ -28,6 +32,7 @@ fun baz(a: WithNullableReference?, b: WithNullableReference) {
takeWithNullableReference(b!!)
}
// @TestKt.class:
// 2 INVOKEVIRTUAL WithPrimitive\.unbox
// 0 INVOKEVIRTUAL WithReference\.unbox
// 3 INVOKEVIRTUAL WithNullableReference\.unbox
@@ -1,9 +1,13 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(val u: Int) {
fun member() {}
}
// FILE: test.kt
fun UInt?.extension() {}
fun test(a: Any, b: Any?) {
@@ -16,6 +20,7 @@ fun test(a: Any, b: Any?) {
}
}
// @TestKt.class:
// 2 INSTANCEOF UInt
// 2 CHECKCAST UInt
@@ -1,7 +1,11 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(val u: Int)
// FILE: test.kt
fun <T> takeVarargs(vararg e: T) {}
fun test(u1: UInt, u2: UInt, us: Array<UInt>) {
@@ -9,6 +13,7 @@ fun test(u1: UInt, u2: UInt, us: Array<UInt>) {
takeVarargs(u1, u2, *us) // 2 box + ...
}
// @TestKt.class:
// 2 INVOKESTATIC UInt\$Erased.box
// 0 INVOKEVIRTUAL UInt.unbox
@@ -1,7 +1,11 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(val value: Int)
// FILE: test.kt
fun test(u1: UInt, u2: UInt) {
val a = u1.value
@@ -9,6 +13,7 @@ fun test(u1: UInt, u2: UInt) {
val c = u1.value + u2.value
}
// @TestKt.class:
// 0 INVOKESTATIC UInt\$Erased.getValue
// 0 INVOKESTATIC UInt\$Erased.box
// 0 INVOKEVIRTUAL UInt.unbox
@@ -28,7 +28,7 @@ fun test() {
fun takeUInt(u: UInt) {}
// 1 INVOKESTATIC UInt\$Erased.box
// 0 INVOKEVIRTUAL UInt.unbox
// 1 INVOKEVIRTUAL UInt.unbox
// 0 INVOKEVIRTUAL UIntIterator.iterator
// 1 INVOKESTATIC kotlin/jvm/internal/ArrayIteratorsKt.iterator
@@ -1,5 +1,7 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(private val value: Int) {
fun asInt() = value
}
@@ -12,12 +14,14 @@ inline class UIntArray(private val intArray: IntArray) {
}
}
// FILE: test.kt
fun UIntArray.swap(i: Int, j: Int) {
this[j] = this[i].also { this[i] = this[j] }
}
// @TestKt.class:
// 0 INVOKEVIRTUAL UInt.unbox
// 0 INVOKESTATIC UInt\$Erased.box
// 0 intValue
// 0 valueOf
@@ -1,12 +1,17 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class UInt(private val u: Int)
// FILE: test.kt
fun test(x: UInt?, y: UInt) {
val a = x ?: y // unbox
val b = x ?: x!! // unbox unbox
}
// @TestKt.class:
// 0 INVOKESTATIC UInt\$Erased.box
// 3 INVOKEVIRTUAL UInt.unbox
@@ -1,9 +1,13 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class Foo(val x: Int) {
fun member() {}
}
// FILE: test.kt
fun Foo.extension() {}
fun <T> T.genericExtension() {}
@@ -13,6 +17,7 @@ fun test(f: Foo?) {
f?.genericExtension()
}
// @TestKt.class:
// 0 INVOKESTATIC Foo\$Erased.box
// 2 INVOKEVIRTUAL Foo.unbox
@@ -1,9 +1,13 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class Result<T>(val a: Any?) {
fun typed(): T = a as T
}
// FILE: test.kt
fun <K> materialize(): K = TODO()
fun test(asInt: Result<Int>, asString: Result<String>, asResult: Result<Result<Int>>) {
@@ -21,6 +25,7 @@ fun test(asInt: Result<Int>, asString: Result<String>, asResult: Result<Result<I
asResult.typed()
}
// @TestKt.class:
// 0 INVOKESTATIC Result\$Erased.box
// 3 INVOKEVIRTUAL Result.unbox
@@ -1,9 +1,13 @@
// !LANGUAGE: +InlineClasses
// FILE: utils.kt
inline class Foo(val x: Int) {
fun member() {}
}
// FILE: test.kt
fun Foo?.extensionOnNullable() {}
fun test(f: Foo?) {
@@ -21,8 +25,8 @@ fun test(f: Foo?) {
}
}
// @TestKt.class:
// 0 INVOKESTATIC Foo\$Erased.box
// 2 INVOKEVIRTUAL Foo.unbox
// 0 valueOf
// 0 intValue