KT-14513 Don't generate delegated property metadata when unused

If the delegated property operators involved are inline, and delegated
property metadata parameter is not used (which is often the case, e.g.,
'lazy'), we can skip those properties in metadata generation.

NOT implemented: special case when only 'kProperty.name' is used by the
corresponding delegated property operators.

Also a sneak fix for KT-34060.
This commit is contained in:
Dmitry Petrov
2019-09-27 14:24:11 +03:00
committed by Dmitry Petrov
parent 92ba298e68
commit a633a33627
29 changed files with 1054 additions and 25 deletions
@@ -0,0 +1,65 @@
class Provider<T>(val _value: T) {
inline operator fun provideDelegate(thisRef: Any?, kProperty: Any?) =
Mut(_value)
}
class Mut<T>(var _value: T) {
inline operator fun getValue(thisRef: Any?, kProperty: Any?) = _value
inline operator fun setValue(thisRef: Any?, kProperty: Any?, newValue: T) {
_value = newValue
}
}
class C {
val delegatedVal by Mut(1)
var delegatedVar by Mut(2)
val delegatedValByProvider by Provider(1)
var delegatedVarByProvider by Provider(2)
}
val topLevelDelegatedVal by Mut(1)
var topLevelDelegatedVar by Mut(2)
val topLevelDelegatedValByProvider by Provider(1)
var topLevelDelegatedVarByProvider by Provider(2)
fun box(): String {
val localDelegatedVal by Mut(1)
var localDelegatedVar by Mut(2)
val localDelegatedValByProvider by Provider(1)
var localDelegatedVarByProvider by Provider(2)
val x = C()
if (x.delegatedVal != 1) throw AssertionError()
if (x.delegatedVar != 2) throw AssertionError()
x.delegatedVar = 3
if (x.delegatedVar != 3) throw AssertionError()
if (x.delegatedValByProvider != 1) throw AssertionError()
if (x.delegatedVarByProvider != 2) throw AssertionError()
x.delegatedVarByProvider = 3
if (x.delegatedVarByProvider != 3) throw AssertionError()
if (topLevelDelegatedVal != 1) throw AssertionError()
if (topLevelDelegatedVar != 2) throw AssertionError()
topLevelDelegatedVar = 3
if (topLevelDelegatedVar != 3) throw AssertionError()
if (topLevelDelegatedValByProvider != 1) throw AssertionError()
if (topLevelDelegatedVarByProvider != 2) throw AssertionError()
topLevelDelegatedVarByProvider = 3
if (topLevelDelegatedVarByProvider != 3) throw AssertionError()
if (localDelegatedVal != 1) throw AssertionError()
if (localDelegatedVar != 2) throw AssertionError()
localDelegatedVar = 3
if (localDelegatedVar != 3) throw AssertionError()
if (localDelegatedValByProvider != 1) throw AssertionError()
if (localDelegatedVarByProvider != 2) throw AssertionError()
localDelegatedVarByProvider = 3
if (localDelegatedVarByProvider != 3) throw AssertionError()
return "OK"
}
@@ -0,0 +1,65 @@
class Provider<T>(val _value: T) {
inline operator fun provideDelegate(thisRef: Any?, kProperty: Any) =
Mut(_value)
}
class Mut<T>(var _value: T) {
inline operator fun getValue(thisRef: Any?, kProperty: Any) = _value
inline operator fun setValue(thisRef: Any?, kProperty: Any, newValue: T) {
_value = newValue
}
}
class C {
val delegatedVal by Mut(1)
var delegatedVar by Mut(2)
val delegatedValByProvider by Provider(1)
var delegatedVarByProvider by Provider(2)
}
val topLevelDelegatedVal by Mut(1)
var topLevelDelegatedVar by Mut(2)
val topLevelDelegatedValByProvider by Provider(1)
var topLevelDelegatedVarByProvider by Provider(2)
fun box(): String {
val localDelegatedVal by Mut(1)
var localDelegatedVar by Mut(2)
val localDelegatedValByProvider by Provider(1)
var localDelegatedVarByProvider by Provider(2)
val x = C()
if (x.delegatedVal != 1) throw AssertionError()
if (x.delegatedVar != 2) throw AssertionError()
x.delegatedVar = 3
if (x.delegatedVar != 3) throw AssertionError()
if (x.delegatedValByProvider != 1) throw AssertionError()
if (x.delegatedVarByProvider != 2) throw AssertionError()
x.delegatedVarByProvider = 3
if (x.delegatedVarByProvider != 3) throw AssertionError()
if (topLevelDelegatedVal != 1) throw AssertionError()
if (topLevelDelegatedVar != 2) throw AssertionError()
topLevelDelegatedVar = 3
if (topLevelDelegatedVar != 3) throw AssertionError()
if (topLevelDelegatedValByProvider != 1) throw AssertionError()
if (topLevelDelegatedVarByProvider != 2) throw AssertionError()
topLevelDelegatedVarByProvider = 3
if (topLevelDelegatedVarByProvider != 3) throw AssertionError()
if (localDelegatedVal != 1) throw AssertionError()
if (localDelegatedVar != 2) throw AssertionError()
localDelegatedVar = 3
if (localDelegatedVar != 3) throw AssertionError()
if (localDelegatedValByProvider != 1) throw AssertionError()
if (localDelegatedVarByProvider != 2) throw AssertionError()
localDelegatedVarByProvider = 3
if (localDelegatedVarByProvider != 3) throw AssertionError()
return "OK"
}
@@ -0,0 +1,76 @@
// MODULE: lib
// FILE: lib.kt
package lib
class Provider<T>(val _value: T) {
inline operator fun provideDelegate(thisRef: Any?, kProperty: Any?) =
Mut(_value)
}
class Mut<T>(var _value: T) {
inline operator fun getValue(thisRef: Any?, kProperty: Any?) = _value
inline operator fun setValue(thisRef: Any?, kProperty: Any?, newValue: T) {
_value = newValue
}
}
// MODULE: main(lib)(lib)
// FILE: main.kt
import lib.*
class C {
val delegatedVal by Mut(1)
var delegatedVar by Mut(2)
val delegatedValByProvider by Provider(1)
var delegatedVarByProvider by Provider(2)
}
val topLevelDelegatedVal by Mut(1)
var topLevelDelegatedVar by Mut(2)
val topLevelDelegatedValByProvider by Provider(1)
var topLevelDelegatedVarByProvider by Provider(2)
fun box(): String {
val localDelegatedVal by Mut(1)
var localDelegatedVar by Mut(2)
val localDelegatedValByProvider by Provider(1)
var localDelegatedVarByProvider by Provider(2)
val x = C()
if (x.delegatedVal != 1) throw AssertionError()
if (x.delegatedVar != 2) throw AssertionError()
x.delegatedVar = 3
if (x.delegatedVar != 3) throw AssertionError()
if (x.delegatedValByProvider != 1) throw AssertionError()
if (x.delegatedVarByProvider != 2) throw AssertionError()
x.delegatedVarByProvider = 3
if (x.delegatedVarByProvider != 3) throw AssertionError()
if (topLevelDelegatedVal != 1) throw AssertionError()
if (topLevelDelegatedVar != 2) throw AssertionError()
topLevelDelegatedVar = 3
if (topLevelDelegatedVar != 3) throw AssertionError()
if (topLevelDelegatedValByProvider != 1) throw AssertionError()
if (topLevelDelegatedVarByProvider != 2) throw AssertionError()
topLevelDelegatedVarByProvider = 3
if (topLevelDelegatedVarByProvider != 3) throw AssertionError()
if (localDelegatedVal != 1) throw AssertionError()
if (localDelegatedVar != 2) throw AssertionError()
localDelegatedVar = 3
if (localDelegatedVar != 3) throw AssertionError()
if (localDelegatedValByProvider != 1) throw AssertionError()
if (localDelegatedVarByProvider != 2) throw AssertionError()
localDelegatedVarByProvider = 3
if (localDelegatedVarByProvider != 3) throw AssertionError()
return "OK"
}
@@ -0,0 +1,76 @@
// MODULE: lib
// FILE: lib.kt
package lib
class Provider<T>(val _value: T) {
inline operator fun provideDelegate(thisRef: Any?, kProperty: Any) =
Mut(_value)
}
class Mut<T>(var _value: T) {
inline operator fun getValue(thisRef: Any?, kProperty: Any) = _value
inline operator fun setValue(thisRef: Any?, kProperty: Any, newValue: T) {
_value = newValue
}
}
// MODULE: main(lib)(lib)
// FILE: main.kt
import lib.*
class C {
val delegatedVal by Mut(1)
var delegatedVar by Mut(2)
val delegatedValByProvider by Provider(1)
var delegatedVarByProvider by Provider(2)
}
val topLevelDelegatedVal by Mut(1)
var topLevelDelegatedVar by Mut(2)
val topLevelDelegatedValByProvider by Provider(1)
var topLevelDelegatedVarByProvider by Provider(2)
fun box(): String {
val localDelegatedVal by Mut(1)
var localDelegatedVar by Mut(2)
val localDelegatedValByProvider by Provider(1)
var localDelegatedVarByProvider by Provider(2)
val x = C()
if (x.delegatedVal != 1) throw AssertionError()
if (x.delegatedVar != 2) throw AssertionError()
x.delegatedVar = 3
if (x.delegatedVar != 3) throw AssertionError()
if (x.delegatedValByProvider != 1) throw AssertionError()
if (x.delegatedVarByProvider != 2) throw AssertionError()
x.delegatedVarByProvider = 3
if (x.delegatedVarByProvider != 3) throw AssertionError()
if (topLevelDelegatedVal != 1) throw AssertionError()
if (topLevelDelegatedVar != 2) throw AssertionError()
topLevelDelegatedVar = 3
if (topLevelDelegatedVar != 3) throw AssertionError()
if (topLevelDelegatedValByProvider != 1) throw AssertionError()
if (topLevelDelegatedVarByProvider != 2) throw AssertionError()
topLevelDelegatedVarByProvider = 3
if (topLevelDelegatedVarByProvider != 3) throw AssertionError()
if (localDelegatedVal != 1) throw AssertionError()
if (localDelegatedVar != 2) throw AssertionError()
localDelegatedVar = 3
if (localDelegatedVar != 3) throw AssertionError()
if (localDelegatedValByProvider != 1) throw AssertionError()
if (localDelegatedVarByProvider != 2) throw AssertionError()
localDelegatedVarByProvider = 3
if (localDelegatedVarByProvider != 3) throw AssertionError()
return "OK"
}
@@ -0,0 +1,17 @@
// WITH_RUNTIME
val topLevelLazyVal by lazy { 1 }
class C {
val memberLazyVal by lazy { 2 }
}
fun box(): String {
val localLazyVal by lazy { 3 }
if (topLevelLazyVal != 1) throw AssertionError()
if (C().memberLazyVal != 2) throw AssertionError()
if (localLazyVal != 3) throw AssertionError()
return "OK"
}
@@ -0,0 +1,59 @@
inline operator fun Double.provideDelegate(thisRef: Any?, kProp: Any?) = this.toLong()
inline operator fun Long.getValue(thisRef: Any?, kProp: Any?) = this.toInt()
inline operator fun Long.getValue(thisRef: Long, kProp: Any?) = this.toInt() + thisRef.toInt()
inline operator fun Long.getValue(thisRef: IntArray, kProp: Any?) = thisRef[this.toInt()]
inline operator fun Long.setValue(thisRef: IntArray, kProp: Any?, newValue: Int) {
thisRef[this.toInt()] = newValue
}
val magic1 by 42.0
val magic2 by 42L
var IntArray.firstElement by 0L
val Long.plus3 by 3L
class C {
inline operator fun Long.getValue(thisRef: IntArray, kProp: Any?) = thisRef[this.toInt()] * 10
inline operator fun Long.setValue(thisRef: IntArray, kProp: Any?, newValue: Int) {
thisRef[this.toInt()] = newValue * 10
}
inline operator fun Long.getValue(thisRef: Long, kProp: Any?) = this.toInt() + thisRef.toInt() * 10
var IntArray.secondElementX10 by 1L
val Long.appendDigit1 by 1L
fun test(intArray: IntArray) {
if (intArray.secondElementX10 != 220) throw AssertionError()
intArray.secondElementX10 = 42
if (intArray.secondElementX10 != 4200) throw AssertionError()
if (42L.appendDigit1 != 421) throw AssertionError()
}
}
fun box(): String {
if (magic1 != 42) throw AssertionError()
if (magic2 != 42) throw AssertionError()
val intArray = IntArray(9) { (it + 1) * 10 + it + 1 } // [ 11, 22, 33, ..., 99 ]
if (10L.plus3 != 13) throw AssertionError()
if (intArray.firstElement != 11) throw AssertionError()
intArray.firstElement = 42
if (intArray.firstElement != 42) throw AssertionError()
val x = C()
x.test(intArray)
return "OK"
}