[FIR2IR] Introduce creation of Fir2Ir lazy classes

This commit is contained in:
Mikhail Glukhikh
2020-06-11 16:14:33 +03:00
parent 5e9291bd8a
commit 0622be14a5
21 changed files with 353 additions and 141 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol
@@ -311,7 +312,7 @@ class Fir2IrClassifierStorage(
return irTypeParameter
}
private fun getCachedIrTypeParameter(
internal fun getCachedIrTypeParameter(
typeParameter: FirTypeParameter,
index: Int = -1,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
@@ -336,7 +337,7 @@ class Fir2IrClassifierStorage(
return null
}
private fun getIrTypeParameter(
internal fun getIrTypeParameter(
typeParameter: FirTypeParameter,
index: Int,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
@@ -417,17 +418,23 @@ class Fir2IrClassifierStorage(
declarationStorage.preCacheBuiltinClassMembers(firClass, irClass)
return irClassSymbol
}
// TODO: remove all this code and change to unbound symbol creation
firClass as FirRegularClass
val classId = firClassSymbol.classId
val parentId = classId.outerClassId
val irParent = declarationStorage.findIrParent(classId.packageFqName, parentId, firClassSymbol)
val irClass = createIrClass(firClass, irParent)
if (irParent is IrExternalPackageFragment) {
declarationStorage.addDeclarationsToExternalClass(firClass as FirRegularClass, irClass)
val irParent = declarationStorage.findIrParent(classId.packageFqName, parentId, firClassSymbol)!!
val symbol = Fir2IrClassSymbol(signature)
val irClass = firClass.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareClass(signature, { symbol }) {
Fir2IrLazyClass(components, startOffset, endOffset, firClass.irOrigin(firProvider), firClass, symbol).apply {
parent = irParent
}
}
}
classCache[firClass] = irClass
// NB: this is needed to prevent recursions in case of self bounds
(irClass as Fir2IrLazyClass).prepareTypeParameters()
return irClass.symbol
return symbol
}
fun getIrTypeParameterSymbol(
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.SymbolTable
@@ -19,4 +21,6 @@ interface Fir2IrComponents {
val declarationStorage: Fir2IrDeclarationStorage
val typeConverter: Fir2IrTypeConverter
val signatureComposer: Fir2IrSignatureComposer
val callGenerator: CallAndReferenceGenerator
val fakeOverrideGenerator: FakeOverrideGenerator
}
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer
import org.jetbrains.kotlin.fir.signaturer.FirMangler
@@ -22,6 +24,8 @@ class Fir2IrComponentsStorage(
override lateinit var classifierStorage: Fir2IrClassifierStorage
override lateinit var declarationStorage: Fir2IrDeclarationStorage
override lateinit var typeConverter: Fir2IrTypeConverter
override lateinit var callGenerator: CallAndReferenceGenerator
override lateinit var fakeOverrideGenerator: FakeOverrideGenerator
override val signatureComposer = FirBasedSignatureComposer(mangler)
}
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.psi
@@ -188,8 +190,7 @@ class Fir2IrConverter(
val components = Fir2IrComponentsStorage(session, scopeSession, symbolTable, builtIns, mangler)
val conversionScope = Fir2IrConversionScope()
val classifierStorage = Fir2IrClassifierStorage(components)
val declarationStorage =
Fir2IrDeclarationStorage(components, moduleDescriptor, classifierStorage, conversionScope, fakeOverrideMode)
val declarationStorage = Fir2IrDeclarationStorage(components, moduleDescriptor)
val typeConverter = Fir2IrTypeConverter(components)
components.declarationStorage = declarationStorage
components.classifierStorage = classifierStorage
@@ -214,12 +215,18 @@ class Fir2IrConverter(
for (firFile in firFiles) {
converter.processClassHeaders(firFile)
}
val fakeOverrideGenerator = FakeOverrideGenerator(
session, scopeSession, classifierStorage, declarationStorage, conversionScope, fakeOverrideMode
)
components.fakeOverrideGenerator = fakeOverrideGenerator
for (firFile in firFiles) {
converter.processFileAndClassMembers(firFile)
}
val fir2irVisitor = Fir2IrVisitor(converter, components, conversionScope, fakeOverrideMode)
declarationStorage.annotationGenerator = AnnotationGenerator(fir2irVisitor)
val callGenerator = CallAndReferenceGenerator(components, fir2irVisitor, conversionScope)
components.callGenerator = callGenerator
declarationStorage.annotationGenerator = AnnotationGenerator(components)
for (firFile in firFiles) {
val irFile = firFile.accept(fir2irVisitor, null) as IrFile
val fileEntry = sourceManager.getOrCreateFileEntry(firFile.psi as KtFile)
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
@@ -23,7 +22,6 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
@@ -49,18 +47,11 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
@OptIn(ObsoleteDescriptorBasedAPI::class)
class Fir2IrDeclarationStorage(
private val components: Fir2IrComponents,
private val moduleDescriptor: FirModuleDescriptor,
classifierStorage: Fir2IrClassifierStorage,
conversionScope: Fir2IrConversionScope,
fakeOverrideMode: FakeOverrideMode
private val moduleDescriptor: FirModuleDescriptor
) : Fir2IrComponents by components {
internal var annotationGenerator: AnnotationGenerator? = null
private val fakeOverrideGenerator = FakeOverrideGenerator(
session, components.scopeSession, classifierStorage, this, conversionScope, fakeOverrideMode
)
private val firSymbolProvider = session.firSymbolProvider
private val firProvider = session.firProvider
@@ -192,83 +183,6 @@ class Fir2IrDeclarationStorage(
}
}
internal fun addDeclarationsToExternalClass(regularClass: FirRegularClass, irClass: IrClass) {
if (regularClass.origin == FirDeclarationOrigin.Java) {
val sam = regularClass.getSamIfAny()
if (sam != null) {
val scope = regularClass.buildUseSiteMemberScope(session, scopeSession)!!
scope.processFunctionsByName(sam.name) {
if (it is FirNamedFunctionSymbol && !it.isFakeOverride) {
irClass.declarations += createIrFunction(it.fir, irClass)
}
}
}
} else if (regularClass.symbol.classId.packageFqName.startsWith(Name.identifier("kotlin"))) {
// Note: yet this is necessary only for *Range / *Progression classes
// due to BE optimizations (for lowering) that use their first / last / step members
// TODO: think how to refactor this piece of code and/or merge it with similar Fir2IrVisitor fragment
val processedNames = mutableSetOf<Name>()
// NB: it's necessary to take all callables from scope,
// e.g. to avoid accessing un-enhanced Java declarations with FirJavaTypeRef etc. inside
val scope = regularClass.buildUseSiteMemberScope(session, scopeSession)!!
scope.processDeclaredConstructors {
irClass.declarations += createIrConstructor(it.fir, irClass)
}
classifierStorage.processClassHeader(regularClass, irClass)
for (declaration in regularClass.declarations) {
when (declaration) {
is FirSimpleFunction -> {
if (declaration.name !in processedNames) {
processedNames += declaration.name
scope.processFunctionsByName(declaration.name) {
if (it is FirNamedFunctionSymbol) {
if (!it.isFakeOverride) {
irClass.declarations += createIrFunction(it.fir, irClass)
} else {
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideFunction(session, it.fir, it)
classifierStorage.preCacheTypeParameters(it.fir)
irClass.declarations += createIrFunction(fakeOverrideSymbol.fir, irClass)
}
}
}
}
}
is FirProperty -> {
if (declaration.name !in processedNames) {
processedNames += declaration.name
scope.processPropertiesByName(declaration.name) {
if (it is FirPropertySymbol) {
if (!it.isFakeOverride) {
irClass.declarations += createIrProperty(it.fir, irClass)
} else {
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideProperty(session, it.fir, it)
classifierStorage.preCacheTypeParameters(it.fir)
irClass.declarations += createIrProperty(fakeOverrideSymbol.fir, irClass)
}
}
}
}
}
is FirRegularClass -> {
val nestedExternalClass = classifierStorage.createIrClass(declaration, irClass)
addDeclarationsToExternalClass(declaration, nestedExternalClass)
irClass.declarations += nestedExternalClass
}
else -> continue
}
}
with(fakeOverrideGenerator) {
irClass.addFakeOverrides(regularClass, processedNames)
}
for (irDeclaration in irClass.declarations) {
irDeclaration.parent = irClass
}
}
irClass.convertAnnotationsFromLibrary(regularClass)
}
internal fun findIrParent(packageFqName: FqName, parentClassId: ClassId?, firBasedSymbol: FirBasedSymbol<*>): IrDeclarationParent? {
return if (parentClassId != null) {
// TODO: this will never work for local classes
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
import org.jetbrains.kotlin.fir.backend.generators.ClassMemberGenerator
import org.jetbrains.kotlin.fir.backend.generators.OperatorExpressionGenerator
import org.jetbrains.kotlin.fir.declarations.*
@@ -63,9 +62,7 @@ class Fir2IrVisitor(
session
)
private val callGenerator = CallAndReferenceGenerator(components, this, conversionScope)
private val memberGenerator = ClassMemberGenerator(components, this, conversionScope, callGenerator, fakeOverrideMode)
private val memberGenerator = ClassMemberGenerator(components, this, conversionScope)
private val operatorGenerator = OperatorExpressionGenerator(components, this, conversionScope)
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.Fir2IrVisitor
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
@@ -23,11 +24,11 @@ import org.jetbrains.kotlin.ir.util.isSetter
* whose targets may vary. After all the necessary pieces of IR elements, e.g., backing field, are ready, this generator splits those
* annotations to the specified targets.
*/
internal class AnnotationGenerator(private val visitor: Fir2IrVisitor) {
internal class AnnotationGenerator(private val components: Fir2IrComponents) : Fir2IrComponents by components {
fun generate(irContainer: IrMutableAnnotationContainer, firContainer: FirAnnotationContainer) {
irContainer.annotations = firContainer.annotations.mapNotNull {
it.accept(visitor, null) as? IrConstructorCall
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
}
@@ -38,7 +39,7 @@ internal class AnnotationGenerator(private val visitor: Fir2IrVisitor) {
it.useSiteTarget == null || !isInConstructor || it.useSiteTarget == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
}
.mapNotNull {
it.accept(visitor, null) as? IrConstructorCall
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
}
@@ -49,7 +50,7 @@ internal class AnnotationGenerator(private val visitor: Fir2IrVisitor) {
it.useSiteTarget == null || it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY
}
.mapNotNull {
it.accept(visitor, null) as? IrConstructorCall
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
}
@@ -63,7 +64,9 @@ internal class AnnotationGenerator(private val visitor: Fir2IrVisitor) {
it.useSiteTarget == AnnotationUseSiteTarget.FIELD ||
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
}
.mapNotNull { it.accept(visitor, null) as? IrConstructorCall }
.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
}
fun generate(propertyAccessor: IrFunction, property: FirProperty) {
@@ -73,25 +76,41 @@ internal class AnnotationGenerator(private val visitor: Fir2IrVisitor) {
if (propertyAccessor.isSetter) {
propertyAccessor.annotations +=
property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_SETTER }
.mapNotNull { it.accept(visitor, null) as? IrConstructorCall }
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_SETTER
}
.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
propertyAccessor.valueParameters.singleOrNull()?.annotations =
propertyAccessor.valueParameters.singleOrNull()?.annotations?.plus(
property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.SETTER_PARAMETER }
.mapNotNull { it.accept(visitor, null) as? IrConstructorCall }
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.SETTER_PARAMETER
}
.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
)!!
} else {
propertyAccessor.annotations +=
property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_GETTER }
.mapNotNull { it.accept(visitor, null) as? IrConstructorCall }
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_GETTER
}
.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
}
propertyAccessor.extensionReceiverParameter?.annotations =
propertyAccessor.extensionReceiverParameter?.annotations?.plus(
property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.RECEIVER }
.mapNotNull { it.accept(visitor, null) as? IrConstructorCall }
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.RECEIVER
}
.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
)!!
}
}
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
internal class CallAndReferenceGenerator(
class CallAndReferenceGenerator(
private val components: Fir2IrComponents,
private val visitor: Fir2IrVisitor,
private val conversionScope: Fir2IrConversionScope
@@ -27,17 +27,11 @@ import org.jetbrains.kotlin.ir.util.*
internal class ClassMemberGenerator(
private val components: Fir2IrComponents,
private val visitor: Fir2IrVisitor,
private val conversionScope: Fir2IrConversionScope,
private val callGenerator: CallAndReferenceGenerator,
fakeOverrideMode: FakeOverrideMode
private val conversionScope: Fir2IrConversionScope
) : Fir2IrComponents by components {
private val annotationGenerator = AnnotationGenerator(visitor)
private val fakeOverrideGenerator = FakeOverrideGenerator(
session, components.scopeSession, classifierStorage, declarationStorage, conversionScope, fakeOverrideMode
)
private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() }
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.Name
internal class FakeOverrideGenerator(
class FakeOverrideGenerator(
private val session: FirSession,
private val scopeSession: ScopeSession,
private val classifierStorage: Fir2IrClassifierStorage,
@@ -56,9 +56,14 @@ internal class FakeOverrideGenerator(
}
fun IrClass.addFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableSet<Name>) {
if (fakeOverrideMode == FakeOverrideMode.NONE) return
declarations += getFakeOverrides(klass, processedCallableNames)
}
fun IrClass.getFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableSet<Name>): List<IrDeclaration> {
val result = mutableListOf<IrDeclaration>()
if (fakeOverrideMode == FakeOverrideMode.NONE) return emptyList()
val superTypesCallableNames = klass.collectCallableNamesFromSupertypes(session)
val useSiteMemberScope = klass.buildUseSiteMemberScope(session, scopeSession) ?: return
val useSiteMemberScope = klass.buildUseSiteMemberScope(session, scopeSession) ?: return emptyList()
for (name in superTypesCallableNames) {
if (name in processedCallableNames) continue
processedCallableNames += name
@@ -82,7 +87,7 @@ internal class FakeOverrideGenerator(
// but fake override itself uses parent from its containing (derived) class
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(baseSymbol) as IrSimpleFunctionSymbol
irFunction.parent = this
declarations += irFunction.withFunction {
result += irFunction.withFunction {
overriddenSymbols = listOf(overriddenSymbol)
}
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalFunction.allowsToHaveFakeOverrideIn(klass)) {
@@ -103,7 +108,7 @@ internal class FakeOverrideGenerator(
}
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(functionSymbol) as IrSimpleFunctionSymbol
irFunction.parent = this
declarations += irFunction.withFunction {
result += irFunction.withFunction {
overriddenSymbols = listOf(overriddenSymbol)
}
}
@@ -122,7 +127,7 @@ internal class FakeOverrideGenerator(
origin = origin
)
irProperty.parent = this
declarations += irProperty.withProperty {
result += irProperty.withProperty {
setOverriddenSymbolsForAccessors(declarationStorage, originalProperty, firOverriddenSymbol = baseSymbol)
}
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.allowsToHaveFakeOverrideIn(klass)) {
@@ -152,13 +157,14 @@ internal class FakeOverrideGenerator(
return@processPropertiesByName
}
irProperty.parent = this
declarations += irProperty.withProperty {
result += irProperty.withProperty {
setOverriddenSymbolsForAccessors(declarationStorage, fakeOverrideProperty, firOverriddenSymbol = propertySymbol)
}
}
}
}
}
return result
}
private fun IrProperty.setOverriddenSymbolsForAccessors(
@@ -0,0 +1,41 @@
/*
* 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.fir.lazy
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.symbols.Fir2IrBindableSymbol
import org.jetbrains.kotlin.ir.IrElementBase
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
abstract class AbstractFir2IrLazyDeclaration<F : FirMemberDeclaration, D : IrSymbolOwner>(
private val components: Fir2IrComponents,
startOffset: Int,
endOffset: Int,
override var origin: IrDeclarationOrigin,
val fir: F,
open val symbol: Fir2IrBindableSymbol<*, D>
) : IrElementBase(startOffset, endOffset), IrDeclaration, Fir2IrComponents by components {
override var metadata: Nothing?
get() = null
set(_) = error("We should never need to store metadata of external declarations.")
override lateinit var parent: IrDeclarationParent
@ObsoleteDescriptorBasedAPI
override val descriptor: DeclarationDescriptor
get() = symbol.descriptor
override var annotations: List<IrConstructorCall> by lazyVar {
fir.annotations.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
}
}
@@ -0,0 +1,222 @@
/*
* 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.fir.lazy
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.declareThisReceiverParameter
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.buildUseSiteMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.isNullableAny
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.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.mapOptimized
import org.jetbrains.kotlin.ir.util.transform
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
class Fir2IrLazyClass(
components: Fir2IrComponents,
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
fir: FirRegularClass,
symbol: Fir2IrClassSymbol
) : AbstractFir2IrLazyDeclaration<FirRegularClass, IrClass>(
components, startOffset, endOffset, origin, fir, symbol
), IrClass {
init {
symbol.bind(this)
classifierStorage.preCacheTypeParameters(fir)
}
internal fun prepareTypeParameters() {
typeParameters = fir.typeParameters.mapIndexedNotNull { index, typeParameter ->
if (typeParameter !is FirTypeParameter) return@mapIndexedNotNull null
classifierStorage.getIrTypeParameter(typeParameter, index).apply {
parent = this@Fir2IrLazyClass
if (superTypes.isEmpty()) {
typeParameter.bounds.mapTo(superTypes) { it.toIrType(typeConverter) }
}
}
}
}
override val source: SourceElement
get() = SourceElement.NO_SOURCE
@ObsoleteDescriptorBasedAPI
override val descriptor: ClassDescriptor
get() = super.descriptor as ClassDescriptor
override val symbol: Fir2IrClassSymbol
get() = super.symbol as Fir2IrClassSymbol
override val name: Name
get() = fir.name
override var visibility: Visibility
get() = fir.visibility
set(_) {
throw AssertionError("Mutating Fir2Ir lazy elements is not possible")
}
override var modality: Modality
get() = fir.modality!!
set(_) {
throw AssertionError("Mutating Fir2Ir lazy elements is not possible")
}
override var attributeOwnerId: IrAttributeContainer
get() = this
set(_) {
throw AssertionError("Mutating Fir2Ir lazy elements is not possible")
}
override val kind: ClassKind
get() = fir.classKind
override val isCompanion: Boolean
get() = fir.isCompanion
override val isInner: Boolean
get() = fir.isInner
override val isData: Boolean
get() = fir.isData
override val isExternal: Boolean
get() = fir.isExternal
override val isInline: Boolean
get() = fir.isInline
override val isExpect: Boolean
get() = fir.isExpect
override val isFun: Boolean
get() = fir.isFun
override var superTypes: List<IrType> by lazyVar {
fir.superTypeRefs.map { it.toIrType(typeConverter) }
}
override lateinit var typeParameters: List<IrTypeParameter>
override var thisReceiver: IrValueParameter? by lazyVar {
symbolTable.enterScope(this)
val typeArguments = fir.typeParameters.map {
IrSimpleTypeImpl(
classifierStorage.getCachedIrTypeParameter(it.symbol.fir)!!.symbol,
hasQuestionMark = false, arguments = emptyList(), annotations = emptyList()
)
}
val receiver = declareThisReceiverParameter(
symbolTable,
thisType = IrSimpleTypeImpl(symbol, hasQuestionMark = false, arguments = typeArguments, annotations = emptyList()),
thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
)
symbolTable.leaveScope(this)
receiver
}
override val declarations: MutableList<IrDeclaration> by lazyVar {
val result = mutableListOf<IrDeclaration>()
val processedNames = mutableSetOf<Name>()
// NB: it's necessary to take all callables from scope,
// e.g. to avoid accessing un-enhanced Java declarations with FirJavaTypeRef etc. inside
val scope = fir.buildUseSiteMemberScope(session, scopeSession)!!
scope.processDeclaredConstructors {
result += declarationStorage.createIrConstructor(it.fir, this)
}
for (declaration in fir.declarations) {
when (declaration) {
is FirSimpleFunction -> {
if (declaration.name !in processedNames) {
processedNames += declaration.name
scope.processFunctionsByName(declaration.name) {
if (it is FirNamedFunctionSymbol) {
if (it.isAbstractMethodOfAny()) {
return@processFunctionsByName
}
result += if (!it.isFakeOverride) {
declarationStorage.createIrFunction(it.fir, irParent = this, origin = origin)
} else {
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideFunction(session, it.fir, it)
classifierStorage.preCacheTypeParameters(it.fir)
declarationStorage.createIrFunction(fakeOverrideSymbol.fir, irParent = this)
}
}
}
}
}
is FirProperty -> {
if (declaration.name !in processedNames) {
processedNames += declaration.name
scope.processPropertiesByName(declaration.name) {
if (it is FirPropertySymbol) {
result += if (!it.isFakeOverride) {
declarationStorage.createIrProperty(it.fir, irParent = this, origin = origin)
} else {
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideProperty(session, it.fir, it)
classifierStorage.preCacheTypeParameters(it.fir)
declarationStorage.createIrProperty(fakeOverrideSymbol.fir, irParent = this)
}
}
}
}
}
is FirRegularClass -> {
val nestedSymbol = classifierStorage.getIrClassSymbol(declaration.symbol)
result += nestedSymbol.owner
}
else -> continue
}
}
with(fakeOverrideGenerator) {
result += getFakeOverrides(fir, processedNames)
}
for (irDeclaration in result) {
irDeclaration.parent = this
}
result
}
private fun FirNamedFunctionSymbol.isAbstractMethodOfAny(): Boolean {
val fir = fir
if (fir.modality != Modality.ABSTRACT) return false
return when (fir.name.asString()) {
"equals" -> fir.valueParameters.singleOrNull()?.returnTypeRef?.isNullableAny == true
"hashCode", "toString" -> fir.valueParameters.isEmpty()
else -> false
}
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitClass(this, data)
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
thisReceiver?.accept(visitor, data)
typeParameters.forEach { it.accept(visitor, data) }
declarations.forEach { it.accept(visitor, data) }
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
thisReceiver = thisReceiver?.transform(transformer, data)
typeParameters = typeParameters.mapOptimized { it.transform(transformer, data) }
declarations.transform { it.transform(transformer, data) }
}
}
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.ir.declarations.lazy
import org.jetbrains.kotlin.ir.declarations.withInitialIr
import kotlin.reflect.KProperty
internal fun <T> lazyVar(initializer: () -> T): UnsafeLazyVar<T> = UnsafeLazyVar(initializer)
fun <T> lazyVar(initializer: () -> T): UnsafeLazyVar<T> = UnsafeLazyVar(initializer)
internal class UnsafeLazyVar<T>(initializer: () -> T) {
class UnsafeLazyVar<T>(initializer: () -> T) {
private var isInitialized = false;
private var initializer: (() -> T)? = initializer
private var _value: Any? = null
@@ -67,7 +67,7 @@ fun IrDeclarationContainer.transformDeclarationsFlat(transformation: (IrDeclarat
/**
* Similar to `map`. Return the same List instance if no element instances have changed.
*/
internal inline fun <reified T : IrElement> List<T>.mapOptimized(transformation: (T) -> IrElement): List<T> {
inline fun <reified T : IrElement> List<T>.mapOptimized(transformation: (T) -> IrElement): List<T> {
var result: ArrayList<T>? = null
for ((i, item) in withIndex()) {
val transformed = transformation(item) as T
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: JavaClass.java
@@ -47,7 +47,7 @@ FILE fqName:<root> fileName:/implicitNotNullOnDelegatedImplementation.kt
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:K2 modality:FINAL visibility:public superTypes:[<root>.JFoo]'
FUN name:foo visibility:public modality:FINAL <> ($this:<root>.K2) returnType:kotlin.String
overridden:
public abstract fun foo (): kotlin.String declared in <root>.IFoo
public open fun foo (): kotlin.String declared in <root>.JFoo
$this: VALUE_PARAMETER name:<this> type:<root>.K2
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.String declared in <root>.K2'
@@ -97,6 +97,7 @@ FILE fqName:<root> fileName:/implicitNotNullOnDelegatedImplementation.kt
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:K4 modality:FINAL visibility:public superTypes:[<root>.JUnrelatedFoo; <root>.IFoo]'
FUN name:foo visibility:public modality:FINAL <> ($this:<root>.K4) returnType:kotlin.String?
overridden:
public open fun foo (): kotlin.String? declared in <root>.JUnrelatedFoo
public abstract fun foo (): kotlin.String declared in <root>.IFoo
$this: VALUE_PARAMETER name:<this> type:<root>.K4
BLOCK_BODY
@@ -87,4 +87,5 @@ FILE fqName:<root> fileName:/samConversionToGeneric.kt
BLOCK_BODY
CALL 'public open fun bar2x <Y> (j2x: <root>.J2X<Y of <root>.H.bar2x?>?): kotlin.Unit declared in <root>.H' type=kotlin.Unit origin=null
<Y>: kotlin.Int?
j2x: GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.String> declared in <root>.test10' type=kotlin.Function1<kotlin.Int, kotlin.String> origin=null
j2x: TYPE_OP type=<root>.J2X<Y of <root>.H.bar2x?>? origin=SAM_CONVERSION typeOperand=<root>.J2X<Y of <root>.H.bar2x?>?
GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.String> declared in <root>.test10' type=kotlin.Function1<kotlin.Int, kotlin.String> origin=null