[FIR2IR] Manage function symbols in declaration storage instead of declaration generator
This is needed to be able to implement creation of unbound symbols for references of corresponding declarations (KT-62856) There was an exception from FIR2IR that was fixed with this change, so fir2ir test expectDeclarationWithWeakIncompatibilities started to pass along with IrActualizer, which reported some new errors
This commit is contained in:
committed by
Space Team
parent
953f6ba6b6
commit
3c0f153de4
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.util.classId
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
@@ -312,9 +313,14 @@ class Fir2IrDeclarationStorage(
|
||||
isLocal: Boolean = false,
|
||||
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null
|
||||
): IrSimpleFunction {
|
||||
val signature = runIf(!isLocal && configuration.linkViaSignatures) {
|
||||
signatureComposer.composeSignature(function, fakeOverrideOwnerLookupTag)
|
||||
}
|
||||
|
||||
val irFunction = callablesGenerator.createIrFunction(
|
||||
function,
|
||||
irParent,
|
||||
createFunctionSymbol(signature),
|
||||
predefinedOrigin,
|
||||
isLocal = isLocal,
|
||||
fakeOverrideOwnerLookupTag = fakeOverrideOwnerLookupTag
|
||||
@@ -324,6 +330,13 @@ class Fir2IrDeclarationStorage(
|
||||
return irFunction
|
||||
}
|
||||
|
||||
internal fun createFunctionSymbol(signature: IdSignature?): IrSimpleFunctionSymbol {
|
||||
return when {
|
||||
signature != null -> symbolTable.referenceSimpleFunction(signature)
|
||||
else -> IrSimpleFunctionSymbolImpl()
|
||||
}
|
||||
}
|
||||
|
||||
private fun cacheIrFunction(function: FirFunction, irFunction: IrSimpleFunction, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?) {
|
||||
when {
|
||||
irFunction.visibility == DescriptorVisibilities.LOCAL -> {
|
||||
|
||||
+25
-27
@@ -307,34 +307,32 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon
|
||||
isOperator: Boolean = false,
|
||||
): IrSimpleFunction {
|
||||
val signature = if (klass.symbol.classId.isLocal) null else components.signatureComposer.composeSignature(syntheticCounterpart)
|
||||
return components.callablesGenerator.declareIrSimpleFunction(signature) { symbol ->
|
||||
components.irFactory.createSimpleFunction(
|
||||
startOffset = UNDEFINED_OFFSET,
|
||||
endOffset = UNDEFINED_OFFSET,
|
||||
origin = origin,
|
||||
name = name,
|
||||
visibility = DescriptorVisibilities.PUBLIC,
|
||||
isInline = false,
|
||||
isExpect = false,
|
||||
returnType = returnType,
|
||||
modality = Modality.OPEN,
|
||||
symbol = symbol,
|
||||
isTailrec = false,
|
||||
isSuspend = false,
|
||||
isOperator = isOperator,
|
||||
isInfix = false,
|
||||
isExternal = false,
|
||||
isFakeOverride = false,
|
||||
).apply {
|
||||
if (otherParameterNeeded) {
|
||||
val irValueParameter = createSyntheticIrParameter(
|
||||
this, syntheticCounterpart.valueParameters.first().name, components.irBuiltIns.anyNType
|
||||
)
|
||||
this.valueParameters = listOf(irValueParameter)
|
||||
}
|
||||
metadata = FirMetadataSource.Function(syntheticCounterpart)
|
||||
val symbol = components.declarationStorage.createFunctionSymbol(signature)
|
||||
return components.irFactory.createSimpleFunction(
|
||||
startOffset = UNDEFINED_OFFSET,
|
||||
endOffset = UNDEFINED_OFFSET,
|
||||
origin = origin,
|
||||
name = name,
|
||||
visibility = DescriptorVisibilities.PUBLIC,
|
||||
isInline = false,
|
||||
isExpect = false,
|
||||
returnType = returnType,
|
||||
modality = Modality.OPEN,
|
||||
symbol = symbol,
|
||||
isTailrec = false,
|
||||
isSuspend = false,
|
||||
isOperator = isOperator,
|
||||
isInfix = false,
|
||||
isExternal = false,
|
||||
isFakeOverride = false,
|
||||
).apply {
|
||||
if (otherParameterNeeded) {
|
||||
val irValueParameter = createSyntheticIrParameter(
|
||||
this, syntheticCounterpart.valueParameters.first().name, components.irBuiltIns.anyNType
|
||||
)
|
||||
this.valueParameters = listOf(irValueParameter)
|
||||
}
|
||||
}.apply {
|
||||
metadata = FirMetadataSource.Function(syntheticCounterpart)
|
||||
setParent(irClass)
|
||||
addDeclarationToParent(this, irClass)
|
||||
dispatchReceiverParameter = generateDispatchReceiverParameter(this)
|
||||
|
||||
+38
-56
@@ -84,6 +84,7 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
|
||||
fun createIrFunction(
|
||||
function: FirFunction,
|
||||
irParent: IrDeclarationParent?,
|
||||
symbol: IrSimpleFunctionSymbol,
|
||||
predefinedOrigin: IrDeclarationOrigin? = null,
|
||||
isLocal: Boolean = false,
|
||||
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
|
||||
@@ -109,26 +110,9 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
|
||||
fakeOverrideOwnerLookupTag
|
||||
)
|
||||
}
|
||||
val parentIsExternal = irParent.isExternalParent()
|
||||
// We don't generate signatures for local classes
|
||||
// We attempt to avoid signature generation for non-local classes, with the following exceptions:
|
||||
// - special mode (generateSignatures) oriented on special backend modes
|
||||
// - lazy classes (they still use signatures)
|
||||
// - primitive types (they can be from built-ins and don't have FIR counterpart)
|
||||
// - overrides and fake overrides (sometimes we perform "receiver replacement" in FIR2IR breaking FIR->IR relation,
|
||||
// or FIR counterpart can be just created on the fly)
|
||||
val signature =
|
||||
runUnless(
|
||||
isLocal ||
|
||||
!configuration.linkViaSignatures && !parentIsExternal &&
|
||||
function.dispatchReceiverType?.isPrimitive != true && function.containerSource == null &&
|
||||
updatedOrigin != IrDeclarationOrigin.FAKE_OVERRIDE && !function.isOverride
|
||||
) {
|
||||
signatureComposer.composeSignature(function, fakeOverrideOwnerLookupTag)
|
||||
}
|
||||
if (parentIsExternal && signature != null) {
|
||||
if (irParent.isExternalParent()) {
|
||||
// For private functions signature is null, fallback to non-lazy function
|
||||
return lazyDeclarationsGenerator.createIrLazyFunction(function as FirSimpleFunction, signature, irParent!!, updatedOrigin)
|
||||
return lazyDeclarationsGenerator.createIrLazyFunction(function as FirSimpleFunction, symbol, irParent!!, updatedOrigin)
|
||||
}
|
||||
val name = simpleFunction?.name
|
||||
?: if (isLambda) SpecialNames.ANONYMOUS else SpecialNames.NO_NAME_PROVIDED
|
||||
@@ -138,44 +122,42 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
|
||||
if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendOrKSuspendFunctionType(session) == true
|
||||
else function.isSuspend
|
||||
val created = function.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrSimpleFunction(signature) { symbol ->
|
||||
classifierStorage.preCacheTypeParameters(function, symbol)
|
||||
irFactory.createSimpleFunction(
|
||||
startOffset = if (updatedOrigin == IrDeclarationOrigin.DELEGATED_MEMBER) SYNTHETIC_OFFSET else startOffset,
|
||||
endOffset = if (updatedOrigin == IrDeclarationOrigin.DELEGATED_MEMBER) SYNTHETIC_OFFSET else endOffset,
|
||||
origin = updatedOrigin,
|
||||
name = name,
|
||||
visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility),
|
||||
isInline = simpleFunction?.isInline == true,
|
||||
isExpect = simpleFunction?.isExpect == true,
|
||||
returnType = function.returnTypeRef.toIrType(),
|
||||
modality = simpleFunction?.modality ?: Modality.FINAL,
|
||||
symbol = symbol,
|
||||
isTailrec = simpleFunction?.isTailRec == true,
|
||||
isSuspend = isSuspend,
|
||||
isOperator = simpleFunction?.isOperator == true,
|
||||
isInfix = simpleFunction?.isInfix == true,
|
||||
isExternal = simpleFunction?.isExternal == true,
|
||||
containerSource = simpleFunction?.containerSource,
|
||||
).apply {
|
||||
metadata = FirMetadataSource.Function(function)
|
||||
declarationStorage.withScope(symbol) {
|
||||
/*
|
||||
* `isLocal = true` indicates that a function is local or member of a local class
|
||||
* containingClassLookupTag allows to distinguish those two cases
|
||||
*/
|
||||
setParent(irParent)
|
||||
if (!(isLocal && function.containingClassLookupTag() == null)) {
|
||||
addDeclarationToParent(this, irParent)
|
||||
}
|
||||
declareParameters(
|
||||
function, irParent,
|
||||
dispatchReceiverType = computeDispatchReceiverType(this, simpleFunction, irParent),
|
||||
isStatic = simpleFunction?.isStatic == true,
|
||||
forSetter = false,
|
||||
)
|
||||
convertAnnotationsForNonDeclaredMembers(function, origin)
|
||||
classifierStorage.preCacheTypeParameters(function, symbol)
|
||||
irFactory.createSimpleFunction(
|
||||
startOffset = if (updatedOrigin == IrDeclarationOrigin.DELEGATED_MEMBER) SYNTHETIC_OFFSET else startOffset,
|
||||
endOffset = if (updatedOrigin == IrDeclarationOrigin.DELEGATED_MEMBER) SYNTHETIC_OFFSET else endOffset,
|
||||
origin = updatedOrigin,
|
||||
name = name,
|
||||
visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility),
|
||||
isInline = simpleFunction?.isInline == true,
|
||||
isExpect = simpleFunction?.isExpect == true,
|
||||
returnType = function.returnTypeRef.toIrType(),
|
||||
modality = simpleFunction?.modality ?: Modality.FINAL,
|
||||
symbol = symbol,
|
||||
isTailrec = simpleFunction?.isTailRec == true,
|
||||
isSuspend = isSuspend,
|
||||
isOperator = simpleFunction?.isOperator == true,
|
||||
isInfix = simpleFunction?.isInfix == true,
|
||||
isExternal = simpleFunction?.isExternal == true,
|
||||
containerSource = simpleFunction?.containerSource,
|
||||
).apply {
|
||||
metadata = FirMetadataSource.Function(function)
|
||||
declarationStorage.withScope(symbol) {
|
||||
/*
|
||||
* `isLocal = true` indicates that a function is local or member of a local class
|
||||
* containingClassLookupTag allows to distinguish those two cases
|
||||
*/
|
||||
setParent(irParent)
|
||||
if (!(isLocal && function.containingClassLookupTag() == null)) {
|
||||
addDeclarationToParent(this, irParent)
|
||||
}
|
||||
declareParameters(
|
||||
function, irParent,
|
||||
dispatchReceiverType = computeDispatchReceiverType(this, simpleFunction, irParent),
|
||||
isStatic = simpleFunction?.isStatic == true,
|
||||
forSetter = false,
|
||||
)
|
||||
convertAnnotationsForNonDeclaredMembers(function, origin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-13
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.lazy.*
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorPublicSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldPublicSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertyPublicSymbolImpl
|
||||
@@ -23,25 +24,21 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components {
|
||||
internal fun createIrLazyFunction(
|
||||
fir: FirSimpleFunction,
|
||||
signature: IdSignature,
|
||||
symbol: IrSimpleFunctionSymbol,
|
||||
lazyParent: IrDeclarationParent,
|
||||
declarationOrigin: IrDeclarationOrigin
|
||||
): IrSimpleFunction {
|
||||
val symbol = symbolTable.referenceSimpleFunction(signature)
|
||||
val irFunction = fir.convertWithOffsets { startOffset, endOffset ->
|
||||
symbolTable.declareSimpleFunction(signature, { symbol }) {
|
||||
val firContainingClass = (lazyParent as? Fir2IrLazyClass)?.fir
|
||||
val isFakeOverride = fir.isFakeOverride(firContainingClass)
|
||||
Fir2IrLazySimpleFunction(
|
||||
components, startOffset, endOffset, declarationOrigin,
|
||||
fir, firContainingClass, symbol, isFakeOverride
|
||||
).apply {
|
||||
this.parent = lazyParent
|
||||
}
|
||||
val firContainingClass = (lazyParent as? Fir2IrLazyClass)?.fir
|
||||
val isFakeOverride = fir.isFakeOverride(firContainingClass)
|
||||
Fir2IrLazySimpleFunction(
|
||||
components, startOffset, endOffset, declarationOrigin,
|
||||
fir, firContainingClass, symbol, isFakeOverride
|
||||
).apply {
|
||||
this.parent = lazyParent
|
||||
prepareTypeParameters()
|
||||
}
|
||||
}
|
||||
// NB: this is needed to prevent recursions in case of self bounds
|
||||
(irFunction as Fir2IrLazySimpleFunction).prepareTypeParameters()
|
||||
return irFunction
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -2,14 +2,14 @@
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
expect class Foo1
|
||||
expect class Foo2
|
||||
<!EXPECT_ACTUAL_INCOMPATIBILITY{JVM}!>expect class Foo1<!>
|
||||
<!EXPECT_ACTUAL_INCOMPATIBILITY{JVM}!>expect class Foo2<!>
|
||||
|
||||
expect fun foo2(): Int
|
||||
|
||||
expect val s: String
|
||||
<!EXPECT_ACTUAL_INCOMPATIBILITY{JVM}!>expect val s: String<!>
|
||||
|
||||
expect open class Foo3
|
||||
<!EXPECT_ACTUAL_INCOMPATIBILITY{JVM}!>expect open class Foo3<!>
|
||||
|
||||
// MODULE: m2-jvm()()(m1-common)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user