[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.descriptors.*
import org.jetbrains.kotlin.fir.declarations.* 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.firProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol
@@ -311,7 +312,7 @@ class Fir2IrClassifierStorage(
return irTypeParameter return irTypeParameter
} }
private fun getCachedIrTypeParameter( internal fun getCachedIrTypeParameter(
typeParameter: FirTypeParameter, typeParameter: FirTypeParameter,
index: Int = -1, index: Int = -1,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
@@ -336,7 +337,7 @@ class Fir2IrClassifierStorage(
return null return null
} }
private fun getIrTypeParameter( internal fun getIrTypeParameter(
typeParameter: FirTypeParameter, typeParameter: FirTypeParameter,
index: Int, index: Int,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
@@ -417,17 +418,23 @@ class Fir2IrClassifierStorage(
declarationStorage.preCacheBuiltinClassMembers(firClass, irClass) declarationStorage.preCacheBuiltinClassMembers(firClass, irClass)
return irClassSymbol return irClassSymbol
} }
// TODO: remove all this code and change to unbound symbol creation firClass as FirRegularClass
val classId = firClassSymbol.classId val classId = firClassSymbol.classId
val parentId = classId.outerClassId val parentId = classId.outerClassId
val irParent = declarationStorage.findIrParent(classId.packageFqName, parentId, firClassSymbol) val irParent = declarationStorage.findIrParent(classId.packageFqName, parentId, firClassSymbol)!!
val irClass = createIrClass(firClass, irParent) val symbol = Fir2IrClassSymbol(signature)
val irClass = firClass.convertWithOffsets { startOffset, endOffset ->
if (irParent is IrExternalPackageFragment) { symbolTable.declareClass(signature, { symbol }) {
declarationStorage.addDeclarationsToExternalClass(firClass as FirRegularClass, irClass) 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( fun getIrTypeParameterSymbol(
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.fir.backend package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.FirSession 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.resolve.ScopeSession
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
@@ -19,4 +21,6 @@ interface Fir2IrComponents {
val declarationStorage: Fir2IrDeclarationStorage val declarationStorage: Fir2IrDeclarationStorage
val typeConverter: Fir2IrTypeConverter val typeConverter: Fir2IrTypeConverter
val signatureComposer: Fir2IrSignatureComposer val signatureComposer: Fir2IrSignatureComposer
val callGenerator: CallAndReferenceGenerator
val fakeOverrideGenerator: FakeOverrideGenerator
} }
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.fir.backend package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.fir.FirSession 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.resolve.ScopeSession
import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer
import org.jetbrains.kotlin.fir.signaturer.FirMangler import org.jetbrains.kotlin.fir.signaturer.FirMangler
@@ -22,6 +24,8 @@ class Fir2IrComponentsStorage(
override lateinit var classifierStorage: Fir2IrClassifierStorage override lateinit var classifierStorage: Fir2IrClassifierStorage
override lateinit var declarationStorage: Fir2IrDeclarationStorage override lateinit var declarationStorage: Fir2IrDeclarationStorage
override lateinit var typeConverter: Fir2IrTypeConverter override lateinit var typeConverter: Fir2IrTypeConverter
override lateinit var callGenerator: CallAndReferenceGenerator
override lateinit var fakeOverrideGenerator: FakeOverrideGenerator
override val signatureComposer = FirBasedSignatureComposer(mangler) 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.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator 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.declarations.*
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
@@ -188,8 +190,7 @@ class Fir2IrConverter(
val components = Fir2IrComponentsStorage(session, scopeSession, symbolTable, builtIns, mangler) val components = Fir2IrComponentsStorage(session, scopeSession, symbolTable, builtIns, mangler)
val conversionScope = Fir2IrConversionScope() val conversionScope = Fir2IrConversionScope()
val classifierStorage = Fir2IrClassifierStorage(components) val classifierStorage = Fir2IrClassifierStorage(components)
val declarationStorage = val declarationStorage = Fir2IrDeclarationStorage(components, moduleDescriptor)
Fir2IrDeclarationStorage(components, moduleDescriptor, classifierStorage, conversionScope, fakeOverrideMode)
val typeConverter = Fir2IrTypeConverter(components) val typeConverter = Fir2IrTypeConverter(components)
components.declarationStorage = declarationStorage components.declarationStorage = declarationStorage
components.classifierStorage = classifierStorage components.classifierStorage = classifierStorage
@@ -214,12 +215,18 @@ class Fir2IrConverter(
for (firFile in firFiles) { for (firFile in firFiles) {
converter.processClassHeaders(firFile) converter.processClassHeaders(firFile)
} }
val fakeOverrideGenerator = FakeOverrideGenerator(
session, scopeSession, classifierStorage, declarationStorage, conversionScope, fakeOverrideMode
)
components.fakeOverrideGenerator = fakeOverrideGenerator
for (firFile in firFiles) { for (firFile in firFiles) {
converter.processFileAndClassMembers(firFile) converter.processFileAndClassMembers(firFile)
} }
val fir2irVisitor = Fir2IrVisitor(converter, components, conversionScope, fakeOverrideMode) 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) { for (firFile in firFiles) {
val irFile = firFile.accept(fir2irVisitor, null) as IrFile val irFile = firFile.accept(fir2irVisitor, null) as IrFile
val fileEntry = sourceManager.getOrCreateFileEntry(firFile.psi as KtFile) 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.descriptors.annotations.Annotations
import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator 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.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter 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.expressions.impl.FirExpressionStub
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.* 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.*
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
@@ -49,18 +47,11 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
class Fir2IrDeclarationStorage( class Fir2IrDeclarationStorage(
private val components: Fir2IrComponents, private val components: Fir2IrComponents,
private val moduleDescriptor: FirModuleDescriptor, private val moduleDescriptor: FirModuleDescriptor
classifierStorage: Fir2IrClassifierStorage,
conversionScope: Fir2IrConversionScope,
fakeOverrideMode: FakeOverrideMode
) : Fir2IrComponents by components { ) : Fir2IrComponents by components {
internal var annotationGenerator: AnnotationGenerator? = null internal var annotationGenerator: AnnotationGenerator? = null
private val fakeOverrideGenerator = FakeOverrideGenerator(
session, components.scopeSession, classifierStorage, this, conversionScope, fakeOverrideMode
)
private val firSymbolProvider = session.firSymbolProvider private val firSymbolProvider = session.firSymbolProvider
private val firProvider = session.firProvider 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? { internal fun findIrParent(packageFqName: FqName, parentClassId: ClassId?, firBasedSymbol: FirBasedSymbol<*>): IrDeclarationParent? {
return if (parentClassId != null) { return if (parentClassId != null) {
// TODO: this will never work for local classes // 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.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.* 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.ClassMemberGenerator
import org.jetbrains.kotlin.fir.backend.generators.OperatorExpressionGenerator import org.jetbrains.kotlin.fir.backend.generators.OperatorExpressionGenerator
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
@@ -63,9 +62,7 @@ class Fir2IrVisitor(
session session
) )
private val callGenerator = CallAndReferenceGenerator(components, this, conversionScope) private val memberGenerator = ClassMemberGenerator(components, this, conversionScope)
private val memberGenerator = ClassMemberGenerator(components, this, conversionScope, callGenerator, fakeOverrideMode)
private val operatorGenerator = OperatorExpressionGenerator(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.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer 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.backend.Fir2IrVisitor
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirValueParameter 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 * 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. * 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) { fun generate(irContainer: IrMutableAnnotationContainer, firContainer: FirAnnotationContainer) {
irContainer.annotations = firContainer.annotations.mapNotNull { 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 it.useSiteTarget == null || !isInConstructor || it.useSiteTarget == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
} }
.mapNotNull { .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 it.useSiteTarget == null || it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY
} }
.mapNotNull { .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.FIELD ||
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_DELEGATE_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) { fun generate(propertyAccessor: IrFunction, property: FirProperty) {
@@ -73,25 +76,41 @@ internal class AnnotationGenerator(private val visitor: Fir2IrVisitor) {
if (propertyAccessor.isSetter) { if (propertyAccessor.isSetter) {
propertyAccessor.annotations += propertyAccessor.annotations +=
property.annotations property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_SETTER } .filter {
.mapNotNull { it.accept(visitor, null) as? IrConstructorCall } it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_SETTER
}
.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
propertyAccessor.valueParameters.singleOrNull()?.annotations = propertyAccessor.valueParameters.singleOrNull()?.annotations =
propertyAccessor.valueParameters.singleOrNull()?.annotations?.plus( propertyAccessor.valueParameters.singleOrNull()?.annotations?.plus(
property.annotations property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.SETTER_PARAMETER } .filter {
.mapNotNull { it.accept(visitor, null) as? IrConstructorCall } it.useSiteTarget == AnnotationUseSiteTarget.SETTER_PARAMETER
}
.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
)!! )!!
} else { } else {
propertyAccessor.annotations += propertyAccessor.annotations +=
property.annotations property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_GETTER } .filter {
.mapNotNull { it.accept(visitor, null) as? IrConstructorCall } it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_GETTER
}
.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}
} }
propertyAccessor.extensionReceiverParameter?.annotations = propertyAccessor.extensionReceiverParameter?.annotations =
propertyAccessor.extensionReceiverParameter?.annotations?.plus( propertyAccessor.extensionReceiverParameter?.annotations?.plus(
property.annotations property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.RECEIVER } .filter {
.mapNotNull { it.accept(visitor, null) as? IrConstructorCall } 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.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
internal class CallAndReferenceGenerator( class CallAndReferenceGenerator(
private val components: Fir2IrComponents, private val components: Fir2IrComponents,
private val visitor: Fir2IrVisitor, private val visitor: Fir2IrVisitor,
private val conversionScope: Fir2IrConversionScope private val conversionScope: Fir2IrConversionScope
@@ -27,17 +27,11 @@ import org.jetbrains.kotlin.ir.util.*
internal class ClassMemberGenerator( internal class ClassMemberGenerator(
private val components: Fir2IrComponents, private val components: Fir2IrComponents,
private val visitor: Fir2IrVisitor, private val visitor: Fir2IrVisitor,
private val conversionScope: Fir2IrConversionScope, private val conversionScope: Fir2IrConversionScope
private val callGenerator: CallAndReferenceGenerator,
fakeOverrideMode: FakeOverrideMode
) : Fir2IrComponents by components { ) : Fir2IrComponents by components {
private val annotationGenerator = AnnotationGenerator(visitor) 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 FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
private fun ConeKotlinType.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.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
internal class FakeOverrideGenerator( class FakeOverrideGenerator(
private val session: FirSession, private val session: FirSession,
private val scopeSession: ScopeSession, private val scopeSession: ScopeSession,
private val classifierStorage: Fir2IrClassifierStorage, private val classifierStorage: Fir2IrClassifierStorage,
@@ -56,9 +56,14 @@ internal class FakeOverrideGenerator(
} }
fun IrClass.addFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableSet<Name>) { 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 superTypesCallableNames = klass.collectCallableNamesFromSupertypes(session)
val useSiteMemberScope = klass.buildUseSiteMemberScope(session, scopeSession) ?: return val useSiteMemberScope = klass.buildUseSiteMemberScope(session, scopeSession) ?: return emptyList()
for (name in superTypesCallableNames) { for (name in superTypesCallableNames) {
if (name in processedCallableNames) continue if (name in processedCallableNames) continue
processedCallableNames += name processedCallableNames += name
@@ -82,7 +87,7 @@ internal class FakeOverrideGenerator(
// but fake override itself uses parent from its containing (derived) class // but fake override itself uses parent from its containing (derived) class
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(baseSymbol) as IrSimpleFunctionSymbol val overriddenSymbol = declarationStorage.getIrFunctionSymbol(baseSymbol) as IrSimpleFunctionSymbol
irFunction.parent = this irFunction.parent = this
declarations += irFunction.withFunction { result += irFunction.withFunction {
overriddenSymbols = listOf(overriddenSymbol) overriddenSymbols = listOf(overriddenSymbol)
} }
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalFunction.allowsToHaveFakeOverrideIn(klass)) { } else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalFunction.allowsToHaveFakeOverrideIn(klass)) {
@@ -103,7 +108,7 @@ internal class FakeOverrideGenerator(
} }
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(functionSymbol) as IrSimpleFunctionSymbol val overriddenSymbol = declarationStorage.getIrFunctionSymbol(functionSymbol) as IrSimpleFunctionSymbol
irFunction.parent = this irFunction.parent = this
declarations += irFunction.withFunction { result += irFunction.withFunction {
overriddenSymbols = listOf(overriddenSymbol) overriddenSymbols = listOf(overriddenSymbol)
} }
} }
@@ -122,7 +127,7 @@ internal class FakeOverrideGenerator(
origin = origin origin = origin
) )
irProperty.parent = this irProperty.parent = this
declarations += irProperty.withProperty { result += irProperty.withProperty {
setOverriddenSymbolsForAccessors(declarationStorage, originalProperty, firOverriddenSymbol = baseSymbol) setOverriddenSymbolsForAccessors(declarationStorage, originalProperty, firOverriddenSymbol = baseSymbol)
} }
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.allowsToHaveFakeOverrideIn(klass)) { } else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.allowsToHaveFakeOverrideIn(klass)) {
@@ -152,13 +157,14 @@ internal class FakeOverrideGenerator(
return@processPropertiesByName return@processPropertiesByName
} }
irProperty.parent = this irProperty.parent = this
declarations += irProperty.withProperty { result += irProperty.withProperty {
setOverriddenSymbolsForAccessors(declarationStorage, fakeOverrideProperty, firOverriddenSymbol = propertySymbol) setOverriddenSymbolsForAccessors(declarationStorage, fakeOverrideProperty, firOverriddenSymbol = propertySymbol)
} }
} }
} }
} }
} }
return result
} }
private fun IrProperty.setOverriddenSymbolsForAccessors( 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 org.jetbrains.kotlin.ir.declarations.withInitialIr
import kotlin.reflect.KProperty 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 isInitialized = false;
private var initializer: (() -> T)? = initializer private var initializer: (() -> T)? = initializer
private var _value: Any? = null 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. * 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 var result: ArrayList<T>? = null
for ((i, item) in withIndex()) { for ((i, item) in withIndex()) {
val transformed = transformation(item) as T val transformed = transformation(item) as T
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_RUNTIME // WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility // !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// JVM_TARGET: 1.8 // JVM_TARGET: 1.8
// WITH_RUNTIME // WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable // !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// JVM_TARGET: 1.8 // JVM_TARGET: 1.8
// WITH_RUNTIME // WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all // !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// JVM_TARGET: 1.8 // JVM_TARGET: 1.8
// WITH_RUNTIME // WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: JavaClass.java // 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]' 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 FUN name:foo visibility:public modality:FINAL <> ($this:<root>.K2) returnType:kotlin.String
overridden: 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 $this: VALUE_PARAMETER name:<this> type:<root>.K2
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.String declared in <root>.K2' 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]' 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? FUN name:foo visibility:public modality:FINAL <> ($this:<root>.K4) returnType:kotlin.String?
overridden: overridden:
public open fun foo (): kotlin.String? declared in <root>.JUnrelatedFoo
public abstract fun foo (): kotlin.String declared in <root>.IFoo public abstract fun foo (): kotlin.String declared in <root>.IFoo
$this: VALUE_PARAMETER name:<this> type:<root>.K4 $this: VALUE_PARAMETER name:<this> type:<root>.K4
BLOCK_BODY BLOCK_BODY
@@ -87,4 +87,5 @@ FILE fqName:<root> fileName:/samConversionToGeneric.kt
BLOCK_BODY 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 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? <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