[FIR] Add Fir2IrLazyField class

This class will be used to delay const evaluation of java fields
until IR tree is built.

#KT-57802
This commit is contained in:
Ivan Kylchik
2023-09-04 12:20:57 +02:00
committed by Space Team
parent bd6607c860
commit fbe00b1b91
3 changed files with 116 additions and 4 deletions
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.java.hasJvmFieldAnnotation
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor
@@ -624,6 +625,17 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
val classId = (irParent as? IrClass)?.classId
val containingClassLookupTag = classId?.toLookupTag()
val signature = signatureComposer.composeSignature(field, containingClassLookupTag)
val parentIsExternal = irParent.isExternalParent()
if (field is FirJavaField && field.isStatic && field.isFinal && parentIsExternal && signature != null) {
// We are going to create IR for Java static final fields lazily because they can refer to some Kotlin const.
// This way we delay const evaluation of Java fields until IR tree is fully built, and we can run IR interpreter.
return lazyDeclarationsGenerator.createIrLazyField(field, signature, irParent!!, origin).apply {
setParent(irParent)
addDeclarationToParent(this, irParent)
}
}
return field.convertWithOffsets { startOffset, endOffset ->
if (signature != null) {
symbolTable.declareField(
@@ -11,13 +11,11 @@ import org.jetbrains.kotlin.fir.backend.convertWithOffsets
import org.jetbrains.kotlin.fir.backend.irOrigin
import org.jetbrains.kotlin.fir.backend.isStubPropertyForPureField
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction
import org.jetbrains.kotlin.fir.lazy.*
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorPublicSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldPublicSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertyPublicSymbolImpl
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.utils.addToStdlib.runIf
@@ -116,4 +114,19 @@ class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2Ir
}
}
}
fun createIrLazyField(
fir: FirField,
signature: IdSignature,
lazyParent: IrDeclarationParent,
declarationOrigin: IrDeclarationOrigin
): IrField {
return fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareField(signature, symbolFactory = { IrFieldPublicSymbolImpl(signature) }) { symbol ->
Fir2IrLazyField(
components, startOffset, endOffset, declarationOrigin, fir, (lazyParent as? Fir2IrLazyClass)?.fir, symbol
)
}
}
}
}
@@ -0,0 +1,87 @@
/*
* Copyright 2010-2023 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.fir.lazy
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.toIrConst
import org.jetbrains.kotlin.fir.declarations.FirField
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.name.Name
class Fir2IrLazyField(
private val components: Fir2IrComponents,
override val startOffset: Int,
override val endOffset: Int,
override var origin: IrDeclarationOrigin,
override val fir: FirField,
val containingClass: FirRegularClass?,
override val symbol: IrFieldSymbol,
) : IrField(), AbstractFir2IrLazyDeclaration<FirField>, Fir2IrComponents by components {
init {
symbol.bind(this)
}
override var annotations: List<IrConstructorCall> by createLazyAnnotations()
override lateinit var parent: IrDeclarationParent
@ObsoleteDescriptorBasedAPI
override val descriptor: PropertyDescriptor
get() = symbol.descriptor
override var isExternal: Boolean
get() = fir.isExternal
set(_) = mutationNotSupported()
override var isFinal: Boolean
get() = fir.isFinal
set(_) = mutationNotSupported()
override var isStatic: Boolean
get() = fir.isStatic
set(_) = mutationNotSupported()
override var name: Name
get() = fir.name
set(_) = mutationNotSupported()
override var visibility: DescriptorVisibility = components.visibilityConverter.convertToDescriptorVisibility(fir.visibility)
set(_) = mutationNotSupported()
override var type: IrType
get() = with(typeConverter) { fir.returnTypeRef.toIrType() }
set(_) = mutationNotSupported()
override var initializer: IrExpressionBody? by lazyVar(lock) {
when (val initializer = fir.unwrapFakeOverrides().initializer) {
is FirConstExpression<*> -> factory.createExpressionBody(initializer.toIrConst(type))
else -> null
}
}
override var correspondingPropertySymbol: IrPropertySymbol?
get() = null
set(_) = mutationNotSupported()
override var metadata: MetadataSource?
get() = null
set(_) = error("We should never need to store metadata of external declarations.")
}