diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt index acbaf02c0cd..6c1fd45cc05 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt @@ -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( diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt index fefd160edb9..952d579e4d0 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt @@ -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 } \ No newline at end of file diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt index 3697f4260de..f3d2e114cd2 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt @@ -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) } \ No newline at end of file diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 992e3be81ed..59aea589411 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -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) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index b8a0b290665..e21d3afffa4 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -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() - // 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 diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 0de3210c7bc..4989800967e 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -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) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AnnotationGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AnnotationGenerator.kt index 4568fc36e2a..51eb4865885 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AnnotationGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AnnotationGenerator.kt @@ -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 + } )!! } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index a6698ffba05..727ecd89541 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -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 diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index 9fe1a084056..95042bfea42 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -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() } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt index 73f8a68cc0d..9a5b51b33d8 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt @@ -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) { - if (fakeOverrideMode == FakeOverrideMode.NONE) return + declarations += getFakeOverrides(klass, processedCallableNames) + } + + fun IrClass.getFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableSet): List { + val result = mutableListOf() + 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( diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt new file mode 100644 index 00000000000..6eb17ec479c --- /dev/null +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt @@ -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( + 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 by lazyVar { + fir.annotations.mapNotNull { + callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall + } + } +} \ No newline at end of file diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt new file mode 100644 index 00000000000..8b2d7eb0073 --- /dev/null +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt @@ -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( + 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 by lazyVar { + fir.superTypeRefs.map { it.toIrType(typeConverter) } + } + + override lateinit var typeParameters: List + + 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 by lazyVar { + val result = mutableListOf() + val processedNames = mutableSetOf() + // 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 accept(visitor: IrElementVisitor, data: D): R = + visitor.visitClass(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + thisReceiver?.accept(visitor, data) + typeParameters.forEach { it.accept(visitor, data) } + declarations.forEach { it.accept(visitor, data) } + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + thisReceiver = thisReceiver?.transform(transformer, data) + typeParameters = typeParameters.mapOptimized { it.transform(transformer, data) } + declarations.transform { it.transform(transformer, data) } + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/lazyUtil.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/lazyUtil.kt index 288304c66dc..2a97c13420d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/lazyUtil.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/lazyUtil.kt @@ -8,9 +8,9 @@ package org.jetbrains.kotlin.ir.declarations.lazy import org.jetbrains.kotlin.ir.declarations.withInitialIr import kotlin.reflect.KProperty -internal fun lazyVar(initializer: () -> T): UnsafeLazyVar = UnsafeLazyVar(initializer) +fun lazyVar(initializer: () -> T): UnsafeLazyVar = UnsafeLazyVar(initializer) -internal class UnsafeLazyVar(initializer: () -> T) { +class UnsafeLazyVar(initializer: () -> T) { private var isInitialized = false; private var initializer: (() -> T)? = initializer private var _value: Any? = null diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt index 75b63903831..a9193e92429 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt @@ -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 List.mapOptimized(transformation: (T) -> IrElement): List { +inline fun List.mapOptimized(transformation: (T) -> IrElement): List { var result: ArrayList? = null for ((i, item) in withIndex()) { val transformed = transformation(item) as T diff --git a/compiler/testData/codegen/box/annotations/annotatedLambda/samFunExpression.kt b/compiler/testData/codegen/box/annotations/annotatedLambda/samFunExpression.kt index 1ba13ba8464..c34c8dd2ca3 100644 --- a/compiler/testData/codegen/box/annotations/annotatedLambda/samFunExpression.kt +++ b/compiler/testData/codegen/box/annotations/annotatedLambda/samFunExpression.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/jvm8/defaults/allCompatibility/bridgeWithJava.kt b/compiler/testData/codegen/box/jvm8/defaults/allCompatibility/bridgeWithJava.kt index a14f3faf7db..fb5dfd1b617 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/allCompatibility/bridgeWithJava.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/allCompatibility/bridgeWithJava.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: all-compatibility -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // JVM_TARGET: 1.8 // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/jvm8/defaults/bridgeWithJava.kt b/compiler/testData/codegen/box/jvm8/defaults/bridgeWithJava.kt index 2490ddfd7bb..73255fd30a3 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/bridgeWithJava.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/bridgeWithJava.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: enable -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // JVM_TARGET: 1.8 // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/bridgeWithJava.kt b/compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/bridgeWithJava.kt index d18b10df4ca..163f988f416 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/bridgeWithJava.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/bridgeWithJava.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: all -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // JVM_TARGET: 1.8 // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/statics/protectedSamConstructor.kt b/compiler/testData/codegen/box/statics/protectedSamConstructor.kt index abfe7ef6883..cc67e0c70ec 100644 --- a/compiler/testData/codegen/box/statics/protectedSamConstructor.kt +++ b/compiler/testData/codegen/box/statics/protectedSamConstructor.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // FILE: JavaClass.java diff --git a/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt b/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt index a902d879d49..dfce6019233 100644 --- a/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt +++ b/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt @@ -47,7 +47,7 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:K2 modality:FINAL visibility:public superTypes:[.JFoo]' FUN name:foo visibility:public modality:FINAL <> ($this:.K2) returnType:kotlin.String overridden: - public abstract fun foo (): kotlin.String declared in .IFoo + public open fun foo (): kotlin.String declared in .JFoo $this: VALUE_PARAMETER name: type:.K2 BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.String declared in .K2' @@ -97,6 +97,7 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:K4 modality:FINAL visibility:public superTypes:[.JUnrelatedFoo; .IFoo]' FUN name:foo visibility:public modality:FINAL <> ($this:.K4) returnType:kotlin.String? overridden: + public open fun foo (): kotlin.String? declared in .JUnrelatedFoo public abstract fun foo (): kotlin.String declared in .IFoo $this: VALUE_PARAMETER name: type:.K4 BLOCK_BODY diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionToGeneric.fir.txt b/compiler/testData/ir/irText/expressions/sam/samConversionToGeneric.fir.txt index e92aa5bc79d..4553cf11aa7 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionToGeneric.fir.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionToGeneric.fir.txt @@ -87,4 +87,5 @@ FILE fqName: fileName:/samConversionToGeneric.kt BLOCK_BODY CALL 'public open fun bar2x (j2x: .J2X.H.bar2x?>?): kotlin.Unit declared in .H' type=kotlin.Unit origin=null : kotlin.Int? - j2x: GET_VAR 'fn: kotlin.Function1 declared in .test10' type=kotlin.Function1 origin=null + j2x: TYPE_OP type=.J2X.H.bar2x?>? origin=SAM_CONVERSION typeOperand=.J2X.H.bar2x?>? + GET_VAR 'fn: kotlin.Function1 declared in .test10' type=kotlin.Function1 origin=null