diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt index 4c27c8e2e60..bc0c2c3a7dd 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt @@ -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( diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt index 16674819be0..4a1a3e5f97c 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt @@ -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 + ) + } + } + } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyField.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyField.kt new file mode 100644 index 00000000000..cbfa9a38907 --- /dev/null +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyField.kt @@ -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, Fir2IrComponents by components { + init { + symbol.bind(this) + } + + override var annotations: List 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.") +} \ No newline at end of file