Support property delegation to inline class values (KT-27070)
This commit is contained in:
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
class Foo {
|
||||
var a: Int = 42
|
||||
var d by Delegate(0)
|
||||
}
|
||||
|
||||
var setterInvoked = 0
|
||||
|
||||
inline class Delegate(val default: Int) {
|
||||
|
||||
operator fun getValue(thisRef: Any?, prop: Any?) =
|
||||
(thisRef as? Foo)?.a ?: default
|
||||
|
||||
operator fun setValue(thisRef: Any?, prop: Any?, newValue: Int) {
|
||||
setterInvoked++
|
||||
if (thisRef is Foo) {
|
||||
thisRef.a = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val x = Foo()
|
||||
if (x.d != 42) throw AssertionError()
|
||||
|
||||
x.d = 1234
|
||||
if (x.d != 1234) throw AssertionError()
|
||||
if (x.a != 1234) throw AssertionError()
|
||||
|
||||
if (setterInvoked != 1) throw AssertionError()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
class Foo {
|
||||
var a: Int = 42
|
||||
var d by DelegateFactory(0)
|
||||
}
|
||||
|
||||
var provideDelegateInvoked = 0
|
||||
var setterInvoked = 0
|
||||
|
||||
inline class DelegateFactory(val default: Int) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: Any?): Delegate {
|
||||
provideDelegateInvoked++
|
||||
return Delegate(default)
|
||||
}
|
||||
}
|
||||
|
||||
inline class Delegate(val default: Int) {
|
||||
|
||||
operator fun getValue(thisRef: Any?, prop: Any?) =
|
||||
(thisRef as? Foo)?.a ?: default
|
||||
|
||||
operator fun setValue(thisRef: Any?, prop: Any?, newValue: Int) {
|
||||
setterInvoked++
|
||||
if (thisRef is Foo) {
|
||||
thisRef.a = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val x = Foo()
|
||||
if (x.d != 42) throw AssertionError()
|
||||
|
||||
x.d = 1234
|
||||
if (x.d != 1234) throw AssertionError()
|
||||
if (x.a != 1234) throw AssertionError()
|
||||
|
||||
if (setterInvoked != 1) throw AssertionError()
|
||||
if (provideDelegateInvoked != 1) throw AssertionError()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
class Foo {
|
||||
companion object {
|
||||
var a: Int = 42
|
||||
var d by Delegate(0)
|
||||
}
|
||||
}
|
||||
|
||||
var setterInvoked = 0
|
||||
|
||||
inline class Delegate(val ignored: Int) {
|
||||
|
||||
operator fun getValue(thisRef: Any?, prop: Any?) = Foo.a
|
||||
|
||||
operator fun setValue(thisRef: Any?, prop: Any?, newValue: Int) {
|
||||
setterInvoked++
|
||||
Foo.a = newValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
if (Foo.d != 42) throw AssertionError()
|
||||
|
||||
Foo.d = 1234
|
||||
if (Foo.d != 1234) throw AssertionError()
|
||||
if (Foo.a != 1234) throw AssertionError()
|
||||
|
||||
if (setterInvoked != 1) throw AssertionError()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JVM_IR, JS, JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
class Foo {
|
||||
companion object {
|
||||
var a: Int = 42
|
||||
@JvmStatic var d by Delegate(0)
|
||||
}
|
||||
}
|
||||
|
||||
var setterInvoked = 0
|
||||
|
||||
inline class Delegate(val ignored: Int) {
|
||||
|
||||
operator fun getValue(thisRef: Any?, prop: Any?) = Foo.a
|
||||
|
||||
operator fun setValue(thisRef: Any?, prop: Any?, newValue: Int) {
|
||||
setterInvoked++
|
||||
Foo.a = newValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
if (Foo.d != 42) throw AssertionError()
|
||||
|
||||
Foo.d = 1234
|
||||
if (Foo.d != 1234) throw AssertionError()
|
||||
if (Foo.a != 1234) throw AssertionError()
|
||||
|
||||
if (setterInvoked != 1) throw AssertionError()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
object Foo {
|
||||
var a: Int = 42
|
||||
var d by Delegate(0)
|
||||
}
|
||||
|
||||
var setterInvoked = 0
|
||||
|
||||
inline class Delegate(val ignored: Int) {
|
||||
|
||||
operator fun getValue(thisRef: Any?, prop: Any?) = Foo.a
|
||||
|
||||
operator fun setValue(thisRef: Any?, prop: Any?, newValue: Int) {
|
||||
setterInvoked++
|
||||
Foo.a = newValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
if (Foo.d != 42) throw AssertionError()
|
||||
|
||||
Foo.d = 1234
|
||||
if (Foo.d != 1234) throw AssertionError()
|
||||
if (Foo.a != 1234) throw AssertionError()
|
||||
|
||||
if (setterInvoked != 1) throw AssertionError()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
var setterInvoked = 0
|
||||
var backing = 42
|
||||
|
||||
inline class Delegate(val ignored: Int) {
|
||||
|
||||
operator fun getValue(thisRef: Any?, prop: Any?) =
|
||||
backing
|
||||
|
||||
operator fun setValue(thisRef: Any?, prop: Any?, newValue: Int) {
|
||||
setterInvoked++
|
||||
backing = newValue
|
||||
}
|
||||
}
|
||||
|
||||
var topLevelD by Delegate(0)
|
||||
|
||||
fun box(): String {
|
||||
if (topLevelD != 42) AssertionError()
|
||||
|
||||
topLevelD = 1234
|
||||
if (topLevelD != 1234) throw AssertionError()
|
||||
if (backing != 1234) throw AssertionError()
|
||||
|
||||
if (setterInvoked != 1) throw AssertionError()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Foo {
|
||||
val a: Int = 42
|
||||
val b by Delegate(0)
|
||||
}
|
||||
|
||||
inline class Delegate(val ignored: Int): ReadOnlyProperty<Foo, Int> {
|
||||
override fun getValue(thisRef: Foo, property: KProperty<*>): Int {
|
||||
return thisRef.a
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val x = Foo()
|
||||
if (x.b != 42) throw AssertionError()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// FILE: Foo.kt
|
||||
class Foo {
|
||||
var a: Int = 42
|
||||
var d by DelegateFactory(0)
|
||||
}
|
||||
|
||||
// FILE: delegates.kt
|
||||
inline class DelegateFactory(val default: Int) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: Any?) = Delegate(default)
|
||||
}
|
||||
|
||||
inline class Delegate(val default: Int) {
|
||||
|
||||
operator fun getValue(thisRef: Any?, prop: Any?) =
|
||||
(thisRef as? Foo)?.a ?: default
|
||||
|
||||
operator fun setValue(thisRef: Any?, prop: Any?, newValue: Int) {
|
||||
if (thisRef is Foo) {
|
||||
thisRef.a = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @Foo.class:
|
||||
// 0 DelegateFactory\.box
|
||||
// 0 DelegateFactory\.unbox
|
||||
// 0 Delegate\.box
|
||||
// 0 Delegate\.unbox
|
||||
// 1 INVOKESTATIC DelegateFactory\.provideDelegate-impl \(ILjava/lang/Object;Ljava/lang/Object;\)I
|
||||
// 1 INVOKESTATIC Delegate\.getValue-impl \(ILjava/lang/Object;Ljava/lang/Object;\)I
|
||||
// 1 INVOKESTATIC Delegate\.setValue-impl \(ILjava/lang/Object;Ljava/lang/Object;I\)V
|
||||
Reference in New Issue
Block a user