[FIR2IR] Remove incorrect usages of Fir2IrDeclarationStorage.getOrCreateIrFunction

`getOrCreateXxx` methods have not very safe semantics: they sometimes
  create an IR declaration if it was missing in caches before. For all
  source declarations, this is not very good semantic, because we have
  strict rules in which order source declarations should be created,
  and usage of `getOrCreateXxx` may break this order.
So it's important to be able to track all invocations of such methods
  to ensure that it's appropriate in each case.
To achieve that, a new `@GetOrCreateSensitiveAPI ` opt-in is introduced
This commit is contained in:
Dmitriy Novozhilov
2023-10-24 15:00:01 +03:00
committed by Space Team
parent af6b71ca2d
commit bced604b57
9 changed files with 23 additions and 5 deletions
@@ -458,6 +458,9 @@ class Fir2IrConverter(
} }
} }
/**
* This function creates IR declarations for callable members without filling their body
*/
private fun processMemberDeclaration( private fun processMemberDeclaration(
declaration: FirDeclaration, declaration: FirDeclaration,
containingClass: FirClass?, containingClass: FirClass?,
@@ -508,7 +511,7 @@ class Fir2IrConverter(
} }
} }
is FirSimpleFunction -> { is FirSimpleFunction -> {
declarationStorage.getOrCreateIrFunction(declaration, parent, isLocal = isInLocalClass) declarationStorage.createAndCacheIrFunction(declaration, parent, isLocal = isInLocalClass)
} }
is FirProperty -> { is FirProperty -> {
if ( if (
@@ -269,6 +269,7 @@ class Fir2IrDeclarationStorage(
return cachedIrCallable return cachedIrCallable
} }
@GetOrCreateSensitiveAPI
fun getOrCreateIrFunction( fun getOrCreateIrFunction(
function: FirFunction, function: FirFunction,
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
@@ -279,6 +280,7 @@ class Fir2IrDeclarationStorage(
return getOrCreateIrFunction(function, { irParent }, predefinedOrigin, isLocal, fakeOverrideOwnerLookupTag) return getOrCreateIrFunction(function, { irParent }, predefinedOrigin, isLocal, fakeOverrideOwnerLookupTag)
} }
@GetOrCreateSensitiveAPI
private fun getOrCreateIrFunction( private fun getOrCreateIrFunction(
function: FirFunction, function: FirFunction,
irParent: () -> IrDeclarationParent?, irParent: () -> IrDeclarationParent?,
@@ -301,7 +303,6 @@ class Fir2IrDeclarationStorage(
return createAndCacheIrFunction(function, irParent(), predefinedOrigin, isLocal, fakeOverrideOwnerLookupTag) return createAndCacheIrFunction(function, irParent(), predefinedOrigin, isLocal, fakeOverrideOwnerLookupTag)
} }
@LeakedDeclarationCaches
fun createAndCacheIrFunction( fun createAndCacheIrFunction(
function: FirFunction, function: FirFunction,
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
@@ -874,6 +875,7 @@ class Fir2IrDeclarationStorage(
getIrConstructorSymbol(fir.symbol) getIrConstructorSymbol(fir.symbol)
} }
else -> { else -> {
@OptIn(GetOrCreateSensitiveAPI::class)
getOrCreateIrFunction( getOrCreateIrFunction(
fir, fir,
{ findIrParent(fir, fakeOverrideOwnerLookupTag) }, { findIrParent(fir, fakeOverrideOwnerLookupTag) },
@@ -1177,6 +1179,13 @@ internal var FirProperty.isStubPropertyForPureField: Boolean? by FirDeclarationD
@RequiresOptIn @RequiresOptIn
annotation class LeakedDeclarationCaches annotation class LeakedDeclarationCaches
/**
* This annotation indicates that an annotated method can create a declaration in ad-hock way, so it should be used with caution
* In most cases, it's recommended to use method which return symbol or which forcefully creates a declaration
*/
@RequiresOptIn
annotation class GetOrCreateSensitiveAPI
@OptIn(UnsafeDuringIrConstructionAPI::class) @OptIn(UnsafeDuringIrConstructionAPI::class)
internal fun <D : IrDeclaration> IrBindableSymbol<*, D>.ownerIfBound(): D? { internal fun <D : IrDeclaration> IrBindableSymbol<*, D>.ownerIfBound(): D? {
return runIf(isBound) { owner } return runIf(isBound) { owner }
@@ -401,7 +401,7 @@ class Fir2IrVisitor(
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): IrElement = whileAnalysing(session, simpleFunction) { override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): IrElement = whileAnalysing(session, simpleFunction) {
val irFunction = if (simpleFunction.visibility == Visibilities.Local) { val irFunction = if (simpleFunction.visibility == Visibilities.Local) {
declarationStorage.getOrCreateIrFunction( declarationStorage.createAndCacheIrFunction(
simpleFunction, irParent = conversionScope.parent(), predefinedOrigin = IrDeclarationOrigin.LOCAL_FUNCTION, isLocal = true simpleFunction, irParent = conversionScope.parent(), predefinedOrigin = IrDeclarationOrigin.LOCAL_FUNCTION, isLocal = true
) )
} else { } else {
@@ -424,7 +424,7 @@ class Fir2IrVisitor(
data: Any? data: Any?
): IrElement = whileAnalysing(session, anonymousFunction) { ): IrElement = whileAnalysing(session, anonymousFunction) {
return anonymousFunction.convertWithOffsets { startOffset, endOffset -> return anonymousFunction.convertWithOffsets { startOffset, endOffset ->
val irFunction = declarationStorage.getOrCreateIrFunction( val irFunction = declarationStorage.createAndCacheIrFunction(
anonymousFunction, anonymousFunction,
irParent = conversionScope.parent(), irParent = conversionScope.parent(),
predefinedOrigin = IrDeclarationOrigin.LOCAL_FUNCTION, predefinedOrigin = IrDeclarationOrigin.LOCAL_FUNCTION,
@@ -173,6 +173,7 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
} }
SymbolKind.FUNCTION_SYMBOL -> { SymbolKind.FUNCTION_SYMBOL -> {
val firSimpleFunction = firDeclaration as FirSimpleFunction val firSimpleFunction = firDeclaration as FirSimpleFunction
@OptIn(GetOrCreateSensitiveAPI::class)
declarationStorage.getOrCreateIrFunction(firSimpleFunction, parent) declarationStorage.getOrCreateIrFunction(firSimpleFunction, parent)
} }
SymbolKind.PROPERTY_SYMBOL -> { SymbolKind.PROPERTY_SYMBOL -> {
@@ -698,6 +698,7 @@ class IrBuiltInsOverFir(
functionSymbol.lazyResolveToPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) functionSymbol.lazyResolveToPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
val irParent = findIrParent(functionSymbol) val irParent = findIrParent(functionSymbol)
@OptIn(GetOrCreateSensitiveAPI::class)
return components.declarationStorage.getOrCreateIrFunction(functionSymbol.fir, irParent).symbol return components.declarationStorage.getOrCreateIrFunction(functionSymbol.fir, irParent).symbol
} }
@@ -214,7 +214,7 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
firSubClass: FirClass, firSubClass: FirClass,
delegateOverride: FirSimpleFunction delegateOverride: FirSimpleFunction
): IrSimpleFunction { ): IrSimpleFunction {
val delegateFunction = declarationStorage.getOrCreateIrFunction( val delegateFunction = declarationStorage.createAndCacheIrFunction(
delegateOverride, subClass, predefinedOrigin = IrDeclarationOrigin.DELEGATED_MEMBER, delegateOverride, subClass, predefinedOrigin = IrDeclarationOrigin.DELEGATED_MEMBER,
fakeOverrideOwnerLookupTag = firSubClass.symbol.toLookupTag() fakeOverrideOwnerLookupTag = firSubClass.symbol.toLookupTag()
) )
@@ -195,6 +195,7 @@ class Fir2IrLazyClass(
symbol.containingClassLookupTag() != ownerLookupTag -> {} symbol.containingClassLookupTag() != ownerLookupTag -> {}
symbol.isAbstractMethodOfAny() -> {} symbol.isAbstractMethodOfAny() -> {}
else -> { else -> {
@OptIn(GetOrCreateSensitiveAPI::class)
result += declarationStorage.getOrCreateIrFunction(symbol.fir, this, origin) result += declarationStorage.getOrCreateIrFunction(symbol.fir, this, origin)
} }
} }
@@ -125,6 +125,7 @@ class Fir2IrLazyPropertyAccessor(
override val initialSignatureFunction: IrFunction? by lazy { override val initialSignatureFunction: IrFunction? by lazy {
val originalFirFunction = (fir as? FirSyntheticPropertyAccessor)?.delegate ?: return@lazy null val originalFirFunction = (fir as? FirSyntheticPropertyAccessor)?.delegate ?: return@lazy null
@OptIn(GetOrCreateSensitiveAPI::class)
declarationStorage.getOrCreateIrFunction(originalFirFunction, parent) declarationStorage.getOrCreateIrFunction(originalFirFunction, parent)
} }
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.lazy package org.jetbrains.kotlin.fir.lazy
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.GetOrCreateSensitiveAPI
import org.jetbrains.kotlin.fir.backend.contextReceiversForFunctionOrContainingProperty import org.jetbrains.kotlin.fir.backend.contextReceiversForFunctionOrContainingProperty
import org.jetbrains.kotlin.fir.backend.generators.Fir2IrCallableDeclarationsGenerator import org.jetbrains.kotlin.fir.backend.generators.Fir2IrCallableDeclarationsGenerator
import org.jetbrains.kotlin.fir.backend.generators.generateOverriddenFunctionSymbols import org.jetbrains.kotlin.fir.backend.generators.generateOverriddenFunctionSymbols
@@ -110,6 +111,7 @@ class Fir2IrLazySimpleFunction(
override val initialSignatureFunction: IrFunction? by lazy { override val initialSignatureFunction: IrFunction? by lazy {
val originalFunction = fir.initialSignatureAttr as? FirFunction ?: return@lazy null val originalFunction = fir.initialSignatureAttr as? FirFunction ?: return@lazy null
@OptIn(GetOrCreateSensitiveAPI::class)
declarationStorage.getOrCreateIrFunction(originalFunction, parent).also { declarationStorage.getOrCreateIrFunction(originalFunction, parent).also {
check(it !== this) { "Initial function can not be the same as remapped function" } check(it !== this) { "Initial function can not be the same as remapped function" }
} }