JVM IR: Fix references to const properties in facade classes

This commit is contained in:
Steven Schäfer
2020-02-06 16:02:38 +01:00
committed by Alexander Udalov
parent d9883067e6
commit 6584df3e01
5 changed files with 40 additions and 10 deletions
@@ -102,6 +102,7 @@ class JvmBackendContext(
internal val multifileFacadesToAdd = mutableMapOf<JvmClassName, MutableList<IrClass>>()
internal val multifileFacadeForPart = mutableMapOf<IrClass, JvmClassName>()
internal val multifileFacadeClassForPart = mutableMapOf<IrClass, IrClass>()
internal val multifileFacadeMemberToPartMember = mutableMapOf<IrFunction, IrFunction>()
internal val hiddenConstructors = mutableMapOf<IrConstructor, IrConstructorImpl>()
@@ -1,10 +1,11 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
@@ -28,12 +29,14 @@ import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
@@ -58,6 +61,7 @@ internal val generateMultifileFacadesPhase = namedIrModulePhase(
)
UpdateFunctionCallSites(functionDelegates).lower(input)
UpdateConstantFacadePropertyReferences(context).lower(input)
context.multifileFacadesToAdd.clear()
@@ -139,6 +143,7 @@ private fun generateMultifileFacades(
for (partClass in partClasses) {
context.multifileFacadeForPart[partClass.attributeOwnerId as IrClass] = jvmClassName
context.multifileFacadeClassForPart[partClass.attributeOwnerId as IrClass] = facadeClass
moveFieldsOfConstProperties(partClass, facadeClass)
@@ -260,3 +265,26 @@ private class UpdateFunctionCallSites(
}
}
}
private class UpdateConstantFacadePropertyReferences(private val context: JvmBackendContext) : ClassLoweringPass {
override fun lower(irClass: IrClass) {
// Find property reference classes for properties whose fields were moved to the facade class.
if (irClass.origin != JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE)
return
val property = (irClass.attributeOwnerId as? IrPropertyReference)?.getter?.owner?.correspondingPropertySymbol?.owner
?: return
val facadeClass = context.multifileFacadeClassForPart[property.parentAsClass.attributeOwnerId]
?: return
if (property.backingField?.shouldMoveToFacade() != true)
return
// Replace the class reference in the body of the property reference class (in getOwner) to refer to the facade class instead.
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement = declaration
override fun visitClassReference(expression: IrClassReference): IrExpression = IrClassReferenceImpl(
expression.startOffset, expression.endOffset, facadeClass.defaultType, facadeClass.symbol, facadeClass.defaultType
)
})
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -21,7 +21,10 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.builders.declarations.addField
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
@@ -97,9 +100,9 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
private fun IrBuilderWithScope.computeSignatureString(expression: IrCallableReference): IrExpression {
return expression.getter?.let { getter ->
localPropertyIndices[getter]?.let { irString("<v#$it>") }
?: if (getter.owner.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) {
// Default property accessor. Compute the signature now, so that we will not get into trouble
// if the getter is transformed to a static method by inline classes lowering.
?: if (getter.owner.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR && getter.owner.parentAsClass.isInline) {
// Default property accessor in an inline class. Compute the signature now, so that we will not
// get into trouble if the getter is transformed to a static method by inline classes lowering.
irString(getter.owner.signature)
} else {
// Delay the computation of the signature until after inline classes lowering to make sure
@@ -1,5 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// KT-11447 Multifile declaration causes IAE: Method can not access a member of class
@@ -1,5 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT