From 8f046d36e0e6291161c0b2b134f1528a25e12578 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Tue, 16 Jan 2024 16:44:55 +0100 Subject: [PATCH] [FIR2IR] Implement support for Fir2IrLazyTypeAlias Fir-based lazy type alias is required in IR text tests to check that lazily loaded IR is equivalent to deserialized IR (module bodies) and does not cause ABI compatibility issues in KLIB-based backends. ^KT-65033 --- .../fir/backend/Fir2IrClassifierStorage.kt | 23 +++++++ .../kotlin/fir/backend/Fir2IrPluginContext.kt | 18 +----- .../Fir2IrLazyDeclarationsGenerator.kt | 15 +++-- .../kotlin/fir/lazy/Fir2IrLazyTypeAlias.kt | 61 +++++++++++++++++++ 4 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyTypeAlias.kt 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 b5e3a468fac..53268ba52c8 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 @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET @@ -399,6 +400,28 @@ class Fir2IrClassifierStorage( internal fun getCachedTypeAlias(firTypeAlias: FirTypeAlias): IrTypeAlias? = typeAliasCache[firTypeAlias] + fun referenceTypeAlias(firTypeAliasSymbol: FirTypeAliasSymbol): IrTypeAlias { + val firTypeAlias = firTypeAliasSymbol.fir + classifierStorage.getCachedTypeAlias(firTypeAlias)?.let { return it } + + val typeAliasId = firTypeAliasSymbol.classId + val parentId = typeAliasId.outerClassId + val parentClass = parentId?.let { session.symbolProvider.getClassLikeSymbolByClassId(it) } + val irParent = declarationStorage.findIrParent( + typeAliasId.packageFqName, + parentClass?.toLookupTag(), + firTypeAliasSymbol, + firTypeAlias.origin + )!! + + val symbol = createTypeAliasSymbol(firTypeAlias) + val irTypeAlias = lazyDeclarationsGenerator.createIrLazyTypeAlias(firTypeAlias, irParent, symbol) + typeAliasCache[firTypeAlias] = irTypeAlias + irTypeAlias.prepareTypeParameters() + + return irTypeAlias + } + // ------------------------------------ code fragments ------------------------------------ fun getCachedIrCodeFragment(codeFragment: FirCodeFragment): IrClass? { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrPluginContext.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrPluginContext.kt index 63b80845e33..7097cc3be21 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrPluginContext.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrPluginContext.kt @@ -16,10 +16,7 @@ import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.scopes.* -import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.linkage.IrDeserializer @@ -81,17 +78,8 @@ class Fir2IrPluginContext( } override fun referenceTypeAlias(classId: ClassId): IrTypeAliasSymbol? { - return referenceClassLikeSymbol(classId, symbolProvider::getClassLikeSymbolByClassId, symbolTable::referenceTypeAlias) - } - - private inline fun referenceClassLikeSymbol( - id: ClassId, - firSymbolExtractor: (ClassId) -> FirClassLikeSymbol<*>?, - irSymbolExtractor: (IdSignature) -> R - ): R? { - val firSymbol = firSymbolExtractor(id) ?: return null - val signature = components.signatureComposer.composeSignature(firSymbol.fir) ?: return null - return irSymbolExtractor(signature) + val firSymbol = symbolProvider.getClassLikeSymbolByClassId(classId) as? FirTypeAliasSymbol ?: return null + return components.classifierStorage.referenceTypeAlias(firSymbol).symbol } override fun referenceConstructors(classId: ClassId): Collection { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt index b30d0a0cb59..94ee5f8f559 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt @@ -12,10 +12,7 @@ import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride import org.jetbrains.kotlin.fir.lazy.* import org.jetbrains.kotlin.fir.unwrapUseSiteSubstitutionOverrides import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.* class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components { internal fun createIrLazyFunction( @@ -75,6 +72,16 @@ class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2Ir Fir2IrLazyClass(components, startOffset, endOffset, firClassOrigin, firClass, symbol, irParent) } + fun createIrLazyTypeAlias( + firTypeAlias: FirTypeAlias, + irParent: IrDeclarationParent, + symbol: IrTypeAliasSymbol + ): Fir2IrLazyTypeAlias = firTypeAlias.convertWithOffsets { startOffset, endOffset -> + Fir2IrLazyTypeAlias( + components, startOffset, endOffset, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB, firTypeAlias, symbol, irParent + ) + } + fun createIrLazyField( fir: FirField, symbol: IrFieldSymbol, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyTypeAlias.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyTypeAlias.kt new file mode 100644 index 00000000000..28bae62c592 --- /dev/null +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyTypeAlias.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.lazy + +import org.jetbrains.kotlin.descriptors.DescriptorVisibility +import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor +import org.jetbrains.kotlin.fir.backend.Fir2IrComponents +import org.jetbrains.kotlin.fir.backend.toIrType +import org.jetbrains.kotlin.fir.declarations.FirTypeAlias +import org.jetbrains.kotlin.fir.declarations.utils.isActual +import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent +import org.jetbrains.kotlin.ir.declarations.IrTypeAlias +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.name.Name + +class Fir2IrLazyTypeAlias( + components: Fir2IrComponents, + override val startOffset: Int, + override val endOffset: Int, + override var origin: IrDeclarationOrigin, + override val fir: FirTypeAlias, + override val symbol: IrTypeAliasSymbol, + override var parent: IrDeclarationParent +) : IrTypeAlias(), AbstractFir2IrLazyDeclaration, Fir2IrTypeParametersContainer, Fir2IrComponents by components { + init { + symbol.bind(this) + classifierStorage.preCacheTypeParameters(fir, symbol) + } + + override var annotations: List by createLazyAnnotations() + override lateinit var typeParameters: List + + @ObsoleteDescriptorBasedAPI + override val descriptor: TypeAliasDescriptor + get() = symbol.descriptor + + override var name: Name + get() = fir.name + set(_) = mutationNotSupported() + + override var visibility: DescriptorVisibility = components.visibilityConverter.convertToDescriptorVisibility(fir.visibility) + set(_) = mutationNotSupported() + + override var isActual: Boolean + get() = fir.isActual + set(_) = mutationNotSupported() + + override var expandedType: IrType by lazyVar(lock) { + fir.expandedTypeRef.toIrType(typeConverter) + } +}