Find correct class owner for inlined local delegated properties
Note that call-site class has no metadata for inlined local delegated properties. Thus, for an inlined local delegated property we should obtain declaration-site class as owner - otherwise, the corresponding `PropertyReference` will have an owner without property metadata.
This commit is contained in:
+22
-8
@@ -94,10 +94,12 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : IrEle
|
|||||||
private val useOptimizedSuperClass =
|
private val useOptimizedSuperClass =
|
||||||
context.state.generateOptimizedCallableReferenceSuperClasses
|
context.state.generateOptimizedCallableReferenceSuperClasses
|
||||||
|
|
||||||
|
private val IrClass.isSynthetic
|
||||||
|
get() = metadata !is MetadataSource.File && metadata !is MetadataSource.Class && metadata !is MetadataSource.Script
|
||||||
|
|
||||||
private val IrMemberAccessExpression<*>.propertyContainer: IrDeclarationParent
|
private val IrMemberAccessExpression<*>.propertyContainer: IrDeclarationParent
|
||||||
get() = if (this is IrLocalDelegatedPropertyReference)
|
get() = if (this is IrLocalDelegatedPropertyReference)
|
||||||
currentClassData?.localPropertyOwner(getter)
|
findClassOwner()
|
||||||
?: throw AssertionError("local property reference before declaration: ${render()}")
|
|
||||||
else
|
else
|
||||||
getter?.owner?.parent ?: field?.owner?.parent ?: error("Property without getter or field: ${dump()}")
|
getter?.owner?.parent ?: field?.owner?.parent ?: error("Property without getter or field: ${dump()}")
|
||||||
|
|
||||||
@@ -106,6 +108,23 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : IrEle
|
|||||||
private val IrField.fakeGetterSignature: String
|
private val IrField.fakeGetterSignature: String
|
||||||
get() = "${JvmAbi.getterName(name.asString())}()${context.defaultMethodSignatureMapper.mapReturnType(this)}"
|
get() = "${JvmAbi.getterName(name.asString())}()${context.defaultMethodSignatureMapper.mapReturnType(this)}"
|
||||||
|
|
||||||
|
private val IrDeclaration.parentsWithSelf: Sequence<IrDeclaration>
|
||||||
|
get() = generateSequence(this) { it.parent as? IrDeclaration }
|
||||||
|
|
||||||
|
private fun IrLocalDelegatedPropertyReference.findClassOwner(): IrClass {
|
||||||
|
val originalBeforeInline = originalBeforeInline
|
||||||
|
if (originalBeforeInline != null) {
|
||||||
|
require(originalBeforeInline is IrLocalDelegatedPropertyReference) {
|
||||||
|
"Original for local delegated property ${render()} has another type: ${originalBeforeInline.render()}"
|
||||||
|
}
|
||||||
|
return originalBeforeInline.findClassOwner()
|
||||||
|
}
|
||||||
|
|
||||||
|
val containingClasses = symbol.owner.parentsWithSelf.filterIsInstance<IrClass>()
|
||||||
|
// Prefer to attach metadata to non-synthetic classes, similarly to how it's done in rememberLocalProperty.
|
||||||
|
return containingClasses.firstOrNull { !it.isSynthetic } ?: containingClasses.first()
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.computeSignatureString(expression: IrMemberAccessExpression<*>): IrExpression {
|
private fun IrBuilderWithScope.computeSignatureString(expression: IrMemberAccessExpression<*>): IrExpression {
|
||||||
if (expression is IrLocalDelegatedPropertyReference) {
|
if (expression is IrLocalDelegatedPropertyReference) {
|
||||||
// Local delegated properties are stored as a plain list, and the runtime library extracts the index from this string:
|
// Local delegated properties are stored as a plain list, and the runtime library extracts the index from this string:
|
||||||
@@ -213,19 +232,14 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : IrEle
|
|||||||
|
|
||||||
val localProperties = mutableListOf<IrLocalDelegatedPropertySymbol>()
|
val localProperties = mutableListOf<IrLocalDelegatedPropertySymbol>()
|
||||||
val localPropertyIndices = mutableMapOf<IrSymbol, Int>()
|
val localPropertyIndices = mutableMapOf<IrSymbol, Int>()
|
||||||
val isSynthetic = irClass.metadata !is MetadataSource.File && irClass.metadata !is MetadataSource.Class &&
|
|
||||||
irClass.metadata !is MetadataSource.Script
|
|
||||||
|
|
||||||
fun localPropertyIndex(getter: IrSymbol): Int? =
|
fun localPropertyIndex(getter: IrSymbol): Int? =
|
||||||
localPropertyIndices[getter] ?: parent?.localPropertyIndex(getter)
|
localPropertyIndices[getter] ?: parent?.localPropertyIndex(getter)
|
||||||
|
|
||||||
fun localPropertyOwner(getter: IrSymbol): IrClass? =
|
|
||||||
if (getter in localPropertyIndices) irClass else parent?.localPropertyOwner(getter)
|
|
||||||
|
|
||||||
fun rememberLocalProperty(property: IrLocalDelegatedProperty) {
|
fun rememberLocalProperty(property: IrLocalDelegatedProperty) {
|
||||||
// Prefer to attach metadata to non-synthetic classes, because it won't be serialized otherwise;
|
// Prefer to attach metadata to non-synthetic classes, because it won't be serialized otherwise;
|
||||||
// if not possible, though, putting it right here will at least allow non-reflective uses.
|
// if not possible, though, putting it right here will at least allow non-reflective uses.
|
||||||
val metadataOwner = generateSequence(this) { it.parent }.find { !it.isSynthetic } ?: this
|
val metadataOwner = generateSequence(this) { it.parent }.find { !it.irClass.isSynthetic } ?: this
|
||||||
metadataOwner.localPropertyIndices[property.getter.symbol] = metadataOwner.localProperties.size
|
metadataOwner.localPropertyIndices[property.getter.symbol] = metadataOwner.localProperties.size
|
||||||
metadataOwner.localProperties.add(property.symbol)
|
metadataOwner.localProperties.add(property.symbol)
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
// IGNORE_INLINER: IR
|
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
// FILE: 1.kt
|
// FILE: 1.kt
|
||||||
package test
|
package test
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_INLINER: IR
|
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
|
|
||||||
import kotlin.reflect.*
|
import kotlin.reflect.*
|
||||||
|
|||||||
Reference in New Issue
Block a user