KT-30419 Box inline classes in return types of covariant overrides
Use boxed version of an inline class in return type position for covariant and generic-specialized overrides. Also fixes KT-35234 and KT-31585.
This commit is contained in:
compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToAny.kt
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
inline class X(val x: Any)
|
||||
|
||||
interface IFoo {
|
||||
fun foo(): Any
|
||||
fun bar(): X
|
||||
}
|
||||
|
||||
class TestX : IFoo {
|
||||
override fun foo(): X = X("O")
|
||||
override fun bar(): X = X("K")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t: IFoo = TestX()
|
||||
val tFoo = t.foo()
|
||||
if (tFoo !is X) {
|
||||
throw AssertionError("X expected: $tFoo")
|
||||
}
|
||||
|
||||
return (t.foo() as X).x.toString() + t.bar().x.toString()
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
interface IFoo {
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
inline class ICFoo(val t: IFoo): IFoo {
|
||||
override fun foo(): String = t.foo()
|
||||
}
|
||||
|
||||
interface IBar {
|
||||
fun bar(): IFoo
|
||||
}
|
||||
|
||||
object FooOK : IFoo {
|
||||
override fun foo(): String = "OK"
|
||||
}
|
||||
|
||||
class Test : IBar {
|
||||
override fun bar(): ICFoo = ICFoo(FooOK)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val test: IBar = Test()
|
||||
val bar = test.bar()
|
||||
if (bar !is ICFoo) {
|
||||
throw AssertionError("bar: $bar")
|
||||
}
|
||||
return bar.foo()
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
inline class X(val x: Char)
|
||||
|
||||
interface IFoo {
|
||||
fun foo(): Any
|
||||
fun bar(): X
|
||||
}
|
||||
|
||||
class TestX : IFoo {
|
||||
override fun foo(): X = X('O')
|
||||
override fun bar(): X = X('K')
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t: IFoo = TestX()
|
||||
val tFoo = t.foo()
|
||||
if (tFoo !is X) {
|
||||
throw AssertionError("X expected: $tFoo")
|
||||
}
|
||||
|
||||
return (t.foo() as X).x.toString() + t.bar().x.toString()
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
interface IFooList {
|
||||
fun foo(): List<String>
|
||||
}
|
||||
|
||||
interface IFooMutableList {
|
||||
fun foo(): MutableList<String>
|
||||
}
|
||||
|
||||
inline class AL(val t: MutableList<String>) : MutableList<String> {
|
||||
override val size: Int get() = t.size
|
||||
override fun get(index: Int): String = t.get(index)
|
||||
override fun set(index: Int, element: String): String = t.set(index, element)
|
||||
override fun contains(element: String): Boolean = t.contains(element)
|
||||
override fun containsAll(elements: Collection<String>): Boolean = t.containsAll(elements)
|
||||
override fun indexOf(element: String): Int = t.indexOf(element)
|
||||
override fun isEmpty(): Boolean = t.isEmpty()
|
||||
override fun iterator(): MutableIterator<String> = t.iterator()
|
||||
override fun lastIndexOf(element: String): Int = t.lastIndexOf(element)
|
||||
override fun add(element: String): Boolean = t.add(element)
|
||||
override fun add(index: Int, element: String) = t.add(index, element)
|
||||
override fun addAll(index: Int, elements: Collection<String>): Boolean = t.addAll(index, elements)
|
||||
override fun addAll(elements: Collection<String>): Boolean = t.addAll(elements)
|
||||
override fun listIterator(): MutableListIterator<String> = t.listIterator()
|
||||
override fun listIterator(index: Int): MutableListIterator<String> = t.listIterator(index)
|
||||
override fun clear() { t.clear() }
|
||||
override fun remove(element: String): Boolean = t.remove(element)
|
||||
override fun removeAll(elements: Collection<String>): Boolean = t.removeAll(elements)
|
||||
override fun removeAt(index: Int): String = t.removeAt(index)
|
||||
override fun retainAll(elements: Collection<String>): Boolean = t.retainAll(elements)
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<String> = t.subList(fromIndex, toIndex)
|
||||
}
|
||||
|
||||
class Test : IFooList, IFooMutableList {
|
||||
val arr = arrayListOf<String>()
|
||||
override fun foo() = AL(arr)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t1: IFooList = Test()
|
||||
val list1 = t1.foo()
|
||||
if (list1 !is AL) throw AssertionError("list1: $list1")
|
||||
|
||||
val t2: IFooMutableList = Test()
|
||||
val list2 = t2.foo()
|
||||
if (list2 !is AL) throw AssertionError("list2: $list2")
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
interface IQ1
|
||||
interface IQ2
|
||||
|
||||
inline class X(val x: Any): IQ1, IQ2
|
||||
|
||||
interface IFoo1 {
|
||||
fun foo(): IQ1
|
||||
}
|
||||
|
||||
interface IFoo2 {
|
||||
fun foo(): IQ2
|
||||
}
|
||||
|
||||
class Test : IFoo1, IFoo2 {
|
||||
override fun foo() = X("OK")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t1: IFoo1 = Test()
|
||||
val x1 = t1.foo()
|
||||
if (x1 !is X) {
|
||||
throw AssertionError("x1: X expected: $x1")
|
||||
}
|
||||
if (x1.x != "OK") {
|
||||
throw AssertionError("x1: ${x1.x}")
|
||||
}
|
||||
|
||||
val t2: IFoo2 = Test()
|
||||
val x2 = t2.foo()
|
||||
if (x2 !is X) {
|
||||
throw AssertionError("x2: X expected: $x2")
|
||||
}
|
||||
if (x2.x != "OK") {
|
||||
throw AssertionError("x2: ${x2.x}")
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
inline class X(val x: Any)
|
||||
|
||||
interface IFoo<T> {
|
||||
fun foo(): T
|
||||
fun bar(): X
|
||||
}
|
||||
|
||||
class TestX : IFoo<X> {
|
||||
override fun foo(): X = X("O")
|
||||
override fun bar(): X = X("K")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t: IFoo<X> = TestX()
|
||||
val tFoo: Any = t.foo()
|
||||
if (tFoo !is X) {
|
||||
throw AssertionError("X expected: $tFoo")
|
||||
}
|
||||
|
||||
return (t.foo() as X).x.toString() + t.bar().x.toString()
|
||||
}
|
||||
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
interface GFoo<out T> {
|
||||
fun foo(): T
|
||||
}
|
||||
|
||||
interface IBar {
|
||||
fun bar(): String
|
||||
}
|
||||
|
||||
interface SFooBar : GFoo<IBar>
|
||||
|
||||
inline class X(val x: String) : IBar {
|
||||
override fun bar(): String = x
|
||||
}
|
||||
|
||||
class Test : SFooBar {
|
||||
override fun foo() = X("OK")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t1: SFooBar = Test()
|
||||
val foo1 = t1.foo()
|
||||
if (foo1 !is X) {
|
||||
throw AssertionError("foo1: $foo1")
|
||||
}
|
||||
val bar1 = foo1.bar()
|
||||
if (bar1 != "OK") {
|
||||
throw AssertionError("bar1: $bar1")
|
||||
}
|
||||
|
||||
val t2: GFoo<Any> = Test()
|
||||
val foo2 = t2.foo()
|
||||
if (foo2 !is IBar) {
|
||||
throw AssertionError("foo2 !is IBar: $foo2")
|
||||
}
|
||||
val bar2 = foo2.bar()
|
||||
if (bar2 != "OK") {
|
||||
throw AssertionError("bar2: $bar2")
|
||||
}
|
||||
if (foo2 !is X) {
|
||||
throw AssertionError("foo2 !is X: $foo2")
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
inline class X(val x: String)
|
||||
|
||||
interface IFoo1<T> {
|
||||
fun foo(x: T): X
|
||||
}
|
||||
|
||||
interface IFoo2 {
|
||||
fun foo(x: String): X
|
||||
}
|
||||
|
||||
class Test : IFoo1<String>, IFoo2 {
|
||||
override fun foo(x: String): X = X(x)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t1: IFoo1<String> = Test()
|
||||
val t2: IFoo2 = Test()
|
||||
return t1.foo("O").x + t2.foo("K").x
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
inline class ResultOrClosed(val x: Any?)
|
||||
|
||||
interface A<T> {
|
||||
fun foo(): T
|
||||
}
|
||||
|
||||
class B : A<ResultOrClosed> {
|
||||
override fun foo(): ResultOrClosed = ResultOrClosed("OK")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val foo: Any = (B() as A<ResultOrClosed>).foo()
|
||||
if (foo !is ResultOrClosed) throw AssertionError("foo: $foo")
|
||||
return foo.x.toString()
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
inline class FieldValue(val value: String)
|
||||
|
||||
enum class RequestFields {
|
||||
ENUM_ONE
|
||||
}
|
||||
|
||||
data class RequestInputParameters(
|
||||
private val backingMap: Map<RequestFields, FieldValue>
|
||||
) : Map<RequestFields, FieldValue> by backingMap
|
||||
|
||||
fun box(): String {
|
||||
val testMap1 = mapOf(RequestFields.ENUM_ONE to FieldValue("value1"))
|
||||
val test1 = testMap1[RequestFields.ENUM_ONE]!!
|
||||
if (test1.value != "value1") throw AssertionError("test1: $test1")
|
||||
|
||||
val testMap2 = RequestInputParameters(mapOf(RequestFields.ENUM_ONE to FieldValue("value2")))
|
||||
val test2 = testMap2[RequestFields.ENUM_ONE]!!
|
||||
if (test2.value != "value2") throw AssertionError("test2: $test2")
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
inline class NumberInlineClass(val value: Double)
|
||||
|
||||
interface TypeAdapter<FROM, TO> {
|
||||
fun decode(string: FROM): TO
|
||||
}
|
||||
|
||||
class StringToDoubleTypeAdapter : TypeAdapter<String, NumberInlineClass> {
|
||||
override fun decode(string: String) = NumberInlineClass(string.toDouble())
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val typeAdapter = StringToDoubleTypeAdapter()
|
||||
val test = typeAdapter.decode("2019")
|
||||
if (test.value != 2019.0) throw AssertionError("test: $test")
|
||||
return "OK"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
inline class NumberInlineClass(val value: Double)
|
||||
|
||||
interface TypeAdapter<FROM, TO> {
|
||||
fun decode(string: FROM): TO
|
||||
}
|
||||
|
||||
class StringToDoubleTypeAdapter : TypeAdapter<String, NumberInlineClass> {
|
||||
override fun decode(string: String) = NumberInlineClass(string.toDouble())
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val string: String? = "2019"
|
||||
val typeAdapter = StringToDoubleTypeAdapter()
|
||||
val test = string?.let(typeAdapter::decode)!!
|
||||
if (test.value != 2019.0) throw AssertionError("test: $test")
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
interface IQ {
|
||||
fun ok(): String
|
||||
}
|
||||
|
||||
inline class X(val t: IQ): IQ {
|
||||
override fun ok(): String = t.ok()
|
||||
}
|
||||
|
||||
interface IFoo1 {
|
||||
fun foo(): Any
|
||||
}
|
||||
|
||||
interface IFoo2 {
|
||||
fun foo(): IQ
|
||||
}
|
||||
|
||||
object OK : IQ {
|
||||
override fun ok(): String = "OK"
|
||||
}
|
||||
|
||||
class Test : IFoo1, IFoo2 {
|
||||
override fun foo(): X = X(OK)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t1: IFoo1 = Test()
|
||||
val foo1 = t1.foo()
|
||||
if (foo1 !is IQ) {
|
||||
throw AssertionError("foo1 !is IQ: $foo1")
|
||||
}
|
||||
val ok1 = foo1.ok()
|
||||
if (ok1 != "OK") {
|
||||
throw AssertionError("ok1: $ok1")
|
||||
}
|
||||
if (foo1 !is X) {
|
||||
throw AssertionError("foo1 !is X: $foo1")
|
||||
}
|
||||
|
||||
val t2: IFoo2 = Test()
|
||||
val foo2 = t2.foo()
|
||||
if (foo2 !is X) {
|
||||
throw AssertionError("foo2 !is X: $foo2")
|
||||
}
|
||||
val ok2 = foo2.ok()
|
||||
if (ok2 != "OK") {
|
||||
throw AssertionError("ok1: $ok2")
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
interface IQ {
|
||||
fun ok(): String
|
||||
}
|
||||
|
||||
inline class X(val t: IQ): IQ {
|
||||
override fun ok(): String = t.ok()
|
||||
}
|
||||
|
||||
interface IFoo1 {
|
||||
fun foo(): IQ
|
||||
}
|
||||
|
||||
interface IFoo2 {
|
||||
fun foo(): Any
|
||||
}
|
||||
|
||||
object OK : IQ {
|
||||
override fun ok(): String = "OK"
|
||||
}
|
||||
|
||||
class Test : IFoo1, IFoo2 {
|
||||
override fun foo(): X = X(OK)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t1: IFoo1 = Test()
|
||||
val foo1 = t1.foo()
|
||||
if (foo1 !is X) {
|
||||
throw AssertionError("foo1 !is X: $foo1")
|
||||
}
|
||||
val ok1 = foo1.ok()
|
||||
if (ok1 != "OK") {
|
||||
throw AssertionError("ok1: $ok1")
|
||||
}
|
||||
|
||||
val t2: IFoo2 = Test()
|
||||
val foo2 = t2.foo()
|
||||
if (foo2 !is IQ) {
|
||||
throw AssertionError("foo2 !is IQ: $foo2")
|
||||
}
|
||||
val ok2 = foo2.ok()
|
||||
if (ok2 != "OK") {
|
||||
throw AssertionError("ok2: $ok2")
|
||||
}
|
||||
if (foo2 !is X) {
|
||||
throw AssertionError("foo2 !is X: $foo2")
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
interface IBase
|
||||
|
||||
interface IQ : IBase {
|
||||
fun ok(): String
|
||||
}
|
||||
|
||||
inline class X(val t: IQ): IQ {
|
||||
override fun ok(): String = t.ok()
|
||||
}
|
||||
|
||||
interface IFoo1 {
|
||||
fun foo(): Any
|
||||
}
|
||||
|
||||
interface IFoo2<T : IBase> {
|
||||
fun foo(): T
|
||||
}
|
||||
|
||||
object OK : IQ {
|
||||
override fun ok(): String = "OK"
|
||||
}
|
||||
|
||||
class Test : IFoo1, IFoo2<IQ> {
|
||||
override fun foo(): X = X(OK)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t1: IFoo1 = Test()
|
||||
val foo1 = t1.foo()
|
||||
if (foo1 !is IQ) {
|
||||
throw AssertionError("foo1 !is IQ: $foo1")
|
||||
}
|
||||
val ok1 = foo1.ok()
|
||||
if (ok1 != "OK") {
|
||||
throw AssertionError("ok1: $ok1")
|
||||
}
|
||||
if (foo1 !is X) {
|
||||
throw AssertionError("foo1 !is X: $foo1")
|
||||
}
|
||||
|
||||
val t2: IFoo2<IQ> = Test()
|
||||
val foo2 = t2.foo()
|
||||
if (foo2 !is X) {
|
||||
throw AssertionError("foo2 !is X: $foo2")
|
||||
}
|
||||
val ok2 = foo2.ok()
|
||||
if (ok2 != "OK") {
|
||||
throw AssertionError("ok1: $ok2")
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
interface IBase
|
||||
|
||||
interface IQ : IBase {
|
||||
fun ok(): String
|
||||
}
|
||||
|
||||
inline class X(val t: IQ): IQ {
|
||||
override fun ok(): String = t.ok()
|
||||
}
|
||||
|
||||
interface IFoo1<T : IBase> {
|
||||
fun foo(): T
|
||||
}
|
||||
|
||||
interface IFoo2 {
|
||||
fun foo(): Any
|
||||
}
|
||||
|
||||
object OK : IQ {
|
||||
override fun ok(): String = "OK"
|
||||
}
|
||||
|
||||
class Test : IFoo1<IQ>, IFoo2 {
|
||||
override fun foo(): X = X(OK)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t1: IFoo1<IQ> = Test()
|
||||
val foo1 = t1.foo()
|
||||
if (foo1 !is X) {
|
||||
throw AssertionError("foo1 !is X: $foo1")
|
||||
}
|
||||
val ok1 = foo1.ok()
|
||||
if (ok1 != "OK") {
|
||||
throw AssertionError("ok1: $ok1")
|
||||
}
|
||||
|
||||
val t2: IFoo2 = Test()
|
||||
val foo2 = t2.foo()
|
||||
if (foo2 !is IQ) {
|
||||
throw AssertionError("foo2 !is IQ: $foo2")
|
||||
}
|
||||
val ok2 = foo2.ok()
|
||||
if (ok2 != "OK") {
|
||||
throw AssertionError("ok2: $ok2")
|
||||
}
|
||||
if (foo2 !is X) {
|
||||
throw AssertionError("foo2 !is X: $foo2")
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
interface IFoo1<out T> {
|
||||
fun foo(): T
|
||||
}
|
||||
|
||||
interface IFoo2<out T> {
|
||||
fun foo(): T
|
||||
}
|
||||
|
||||
inline class X(val x: String)
|
||||
|
||||
class Test : IFoo1<X>, IFoo2<X> {
|
||||
override fun foo(): X = X("OK")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val t1: IFoo1<Any> = Test()
|
||||
val foo1 = t1.foo()
|
||||
if (foo1 !is X) {
|
||||
throw AssertionError("foo1 !is X: $foo1")
|
||||
}
|
||||
if (foo1.x != "OK") {
|
||||
throw AssertionError("foo1.x != 'OK': $foo1")
|
||||
}
|
||||
|
||||
val t2: IFoo2<Any> = Test()
|
||||
val foo2 = t2.foo()
|
||||
if (foo2 !is X) {
|
||||
throw AssertionError("foo2 !is X: $foo2")
|
||||
}
|
||||
if (foo2.x != "OK") {
|
||||
throw AssertionError("foo2.x != 'OK': $foo2")
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user