FIR2IR: bind fake override calls via symbol table
This commit is contained in:
committed by
teamcity
parent
d4cdf874be
commit
5a44fda42c
+62
-14
@@ -405,17 +405,32 @@ class Fir2IrDeclarationStorage(
|
|||||||
if (function is FirSimpleFunction) getCachedIrFunction(function)
|
if (function is FirSimpleFunction) getCachedIrFunction(function)
|
||||||
else localStorage.getLocalFunction(function)
|
else localStorage.getLocalFunction(function)
|
||||||
|
|
||||||
|
fun getCachedIrFunction(function: FirSimpleFunction): IrSimpleFunction? {
|
||||||
|
return if (function.visibility == Visibilities.Local) {
|
||||||
|
localStorage.getLocalFunction(function)
|
||||||
|
} else {
|
||||||
|
functionCache[function]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getCachedIrFunction(
|
fun getCachedIrFunction(
|
||||||
function: FirSimpleFunction,
|
function: FirSimpleFunction,
|
||||||
signatureCalculator: (FirSimpleFunction) -> IdSignature? = { null }
|
dispatchReceiverLookupTag: ConeClassLikeLookupTag?,
|
||||||
|
signatureCalculator: (FirSimpleFunction) -> IdSignature?
|
||||||
): IrSimpleFunction? {
|
): IrSimpleFunction? {
|
||||||
return if (function.visibility == Visibilities.Local) {
|
return if (function.visibility == Visibilities.Local) {
|
||||||
localStorage.getLocalFunction(function)
|
localStorage.getLocalFunction(function)
|
||||||
} else {
|
} else {
|
||||||
functionCache[function] ?: signatureCalculator(function)?.let { signature ->
|
val isFakeOverride = dispatchReceiverLookupTag != null &&
|
||||||
|
dispatchReceiverLookupTag !is ConeClassLookupTagWithFixedSymbol &&
|
||||||
|
dispatchReceiverLookupTag != function.containingClass()
|
||||||
|
val cached = if (isFakeOverride) null else functionCache[function]
|
||||||
|
cached ?: signatureCalculator(function)?.let { signature ->
|
||||||
symbolTable.referenceSimpleFunctionIfAny(signature)?.let { irFunctionSymbol ->
|
symbolTable.referenceSimpleFunctionIfAny(signature)?.let { irFunctionSymbol ->
|
||||||
val irFunction = irFunctionSymbol.owner
|
val irFunction = irFunctionSymbol.owner
|
||||||
functionCache[function] = irFunction
|
if (!isFakeOverride) {
|
||||||
|
functionCache[function] = irFunction
|
||||||
|
}
|
||||||
irFunction
|
irFunction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -874,14 +889,23 @@ class Fir2IrDeclarationStorage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getCachedIrProperty(property: FirProperty): IrProperty? = propertyCache[property]
|
||||||
|
|
||||||
fun getCachedIrProperty(
|
fun getCachedIrProperty(
|
||||||
property: FirProperty,
|
property: FirProperty,
|
||||||
signatureCalculator: (FirProperty) -> IdSignature? = { null }
|
dispatchReceiverLookupTag: ConeClassLikeLookupTag?,
|
||||||
|
signatureCalculator: (FirProperty) -> IdSignature?
|
||||||
): IrProperty? {
|
): IrProperty? {
|
||||||
return propertyCache[property] ?: signatureCalculator(property)?.let { signature ->
|
val isFakeOverride = dispatchReceiverLookupTag != null &&
|
||||||
|
dispatchReceiverLookupTag !is ConeClassLookupTagWithFixedSymbol &&
|
||||||
|
dispatchReceiverLookupTag != property.containingClass()
|
||||||
|
val cached = if (isFakeOverride) null else propertyCache[property]
|
||||||
|
return cached ?: signatureCalculator(property)?.let { signature ->
|
||||||
symbolTable.referencePropertyIfAny(signature)?.let { irPropertySymbol ->
|
symbolTable.referencePropertyIfAny(signature)?.let { irPropertySymbol ->
|
||||||
val irProperty = irPropertySymbol.owner
|
val irProperty = irPropertySymbol.owner
|
||||||
propertyCache[property] = irProperty
|
if (!isFakeOverride) {
|
||||||
|
propertyCache[property] = irProperty
|
||||||
|
}
|
||||||
irProperty
|
irProperty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1099,8 @@ class Fir2IrDeclarationStorage(
|
|||||||
val fir = firConstructorSymbol.fir
|
val fir = firConstructorSymbol.fir
|
||||||
return getIrCallableSymbol(
|
return getIrCallableSymbol(
|
||||||
firConstructorSymbol,
|
firConstructorSymbol,
|
||||||
getCachedIrDeclaration = ::getCachedIrConstructor,
|
dispatchReceiverLookupTag = null,
|
||||||
|
getCachedIrDeclaration = { constructor: FirConstructor, _, calculator -> getCachedIrConstructor(constructor, calculator) },
|
||||||
createIrDeclaration = { parent, origin -> createIrConstructor(fir, parent as IrClass, predefinedOrigin = origin) },
|
createIrDeclaration = { parent, origin -> createIrConstructor(fir, parent as IrClass, predefinedOrigin = origin) },
|
||||||
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
|
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
|
||||||
val symbol = Fir2IrConstructorSymbol(signature)
|
val symbol = Fir2IrConstructorSymbol(signature)
|
||||||
@@ -1109,8 +1134,13 @@ class Fir2IrDeclarationStorage(
|
|||||||
createIrFunction(fir, irParent, predefinedOrigin = declarationOrigin).symbol
|
createIrFunction(fir, irParent, predefinedOrigin = declarationOrigin).symbol
|
||||||
}
|
}
|
||||||
is FirSimpleFunction -> {
|
is FirSimpleFunction -> {
|
||||||
|
val unmatchedReceiver = dispatchReceiverLookupTag != firFunctionSymbol.containingClass()
|
||||||
|
if (unmatchedReceiver) {
|
||||||
|
generateLazyFakeOverrides(fir.name, dispatchReceiverLookupTag)
|
||||||
|
}
|
||||||
val originalSymbol = getIrCallableSymbol(
|
val originalSymbol = getIrCallableSymbol(
|
||||||
firFunctionSymbol,
|
firFunctionSymbol,
|
||||||
|
dispatchReceiverLookupTag,
|
||||||
getCachedIrDeclaration = ::getCachedIrFunction,
|
getCachedIrDeclaration = ::getCachedIrFunction,
|
||||||
createIrDeclaration = { parent, origin -> createIrFunction(fir, parent, predefinedOrigin = origin) },
|
createIrDeclaration = { parent, origin -> createIrFunction(fir, parent, predefinedOrigin = origin) },
|
||||||
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
|
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
|
||||||
@@ -1135,14 +1165,14 @@ class Fir2IrDeclarationStorage(
|
|||||||
irFunction
|
irFunction
|
||||||
}
|
}
|
||||||
) as IrFunctionSymbol
|
) as IrFunctionSymbol
|
||||||
if (dispatchReceiverLookupTag != null && dispatchReceiverLookupTag != firFunctionSymbol.containingClass()) {
|
if (dispatchReceiverLookupTag is ConeClassLookupTagWithFixedSymbol && unmatchedReceiver) {
|
||||||
val dispatchReceiverIrClass =
|
val dispatchReceiverIrClass =
|
||||||
classifierStorage.getIrClassSymbol(dispatchReceiverLookupTag.toSymbol(session) as FirClassSymbol).owner
|
classifierStorage.getIrClassSymbol(dispatchReceiverLookupTag.toSymbol(session) as FirClassSymbol).owner
|
||||||
dispatchReceiverIrClass.declarations.find {
|
dispatchReceiverIrClass.declarations.find {
|
||||||
it is IrSimpleFunction && it.isFakeOverride && it.name == fir.name &&
|
it is IrSimpleFunction && it.isFakeOverride && it.name == fir.name &&
|
||||||
it.overrides(originalSymbol.owner as IrSimpleFunction)
|
it.overrides(originalSymbol.owner as IrSimpleFunction)
|
||||||
}?.symbol as? IrFunctionSymbol
|
}?.symbol as? IrFunctionSymbol
|
||||||
?: originalSymbol // Fallback (normally we should not be here, but f/o are bound too late)
|
?: originalSymbol // Fallback (normally we should not be here, but f/o are bound too late for local classes)
|
||||||
} else {
|
} else {
|
||||||
originalSymbol
|
originalSymbol
|
||||||
}
|
}
|
||||||
@@ -1162,8 +1192,13 @@ class Fir2IrDeclarationStorage(
|
|||||||
if (fir.isLocal) {
|
if (fir.isLocal) {
|
||||||
return localStorage.getDelegatedProperty(fir)?.symbol ?: getIrVariableSymbol(fir)
|
return localStorage.getDelegatedProperty(fir)?.symbol ?: getIrVariableSymbol(fir)
|
||||||
}
|
}
|
||||||
|
val unmatchedReceiver = dispatchReceiverLookupTag != firPropertySymbol.containingClass()
|
||||||
|
if (unmatchedReceiver) {
|
||||||
|
generateLazyFakeOverrides(fir.name, dispatchReceiverLookupTag)
|
||||||
|
}
|
||||||
val originalSymbol = getIrCallableSymbol(
|
val originalSymbol = getIrCallableSymbol(
|
||||||
firPropertySymbol,
|
firPropertySymbol,
|
||||||
|
dispatchReceiverLookupTag,
|
||||||
getCachedIrDeclaration = ::getCachedIrProperty,
|
getCachedIrDeclaration = ::getCachedIrProperty,
|
||||||
createIrDeclaration = { parent, origin -> createIrProperty(fir, parent, predefinedOrigin = origin) },
|
createIrDeclaration = { parent, origin -> createIrProperty(fir, parent, predefinedOrigin = origin) },
|
||||||
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
|
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
|
||||||
@@ -1185,33 +1220,46 @@ class Fir2IrDeclarationStorage(
|
|||||||
return symbol
|
return symbol
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return if (dispatchReceiverLookupTag != null && dispatchReceiverLookupTag != firPropertySymbol.containingClass()) {
|
return if (dispatchReceiverLookupTag is ConeClassLookupTagWithFixedSymbol &&
|
||||||
|
dispatchReceiverLookupTag != firPropertySymbol.containingClass()
|
||||||
|
) {
|
||||||
val dispatchReceiverIrClass =
|
val dispatchReceiverIrClass =
|
||||||
classifierStorage.getIrClassSymbol(dispatchReceiverLookupTag.toSymbol(session) as FirClassSymbol).owner
|
classifierStorage.getIrClassSymbol(dispatchReceiverLookupTag.toSymbol(session) as FirClassSymbol).owner
|
||||||
dispatchReceiverIrClass.declarations.find {
|
dispatchReceiverIrClass.declarations.find {
|
||||||
it is IrProperty && it.isFakeOverride && it.name == fir.name && it.overrides(originalSymbol.owner as IrProperty)
|
it is IrProperty && it.isFakeOverride && it.name == fir.name && it.overrides(originalSymbol.owner as IrProperty)
|
||||||
}?.symbol as? IrPropertySymbol
|
}?.symbol as? IrPropertySymbol
|
||||||
?: originalSymbol // Fallback (normally we should not be here, but f/o are bound too late)
|
?: originalSymbol // Fallback (normally we should not be here, but f/o are bound too late for local classes)
|
||||||
} else {
|
} else {
|
||||||
originalSymbol
|
originalSymbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateLazyFakeOverrides(name: Name, dispatchReceiverLookupTag: ConeClassLikeLookupTag?) {
|
||||||
|
val firClassSymbol = dispatchReceiverLookupTag?.toSymbol(session) as? FirClassSymbol
|
||||||
|
if (firClassSymbol != null) {
|
||||||
|
val irClass = classifierStorage.getIrClassSymbol(firClassSymbol).owner
|
||||||
|
if (irClass is Fir2IrLazyClass) {
|
||||||
|
irClass.getFakeOverridesByName(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private inline fun <
|
private inline fun <
|
||||||
reified FS : FirCallableSymbol<*>,
|
reified FS : FirCallableSymbol<*>,
|
||||||
reified F : FirCallableDeclaration,
|
reified F : FirCallableDeclaration,
|
||||||
I : IrSymbolOwner,
|
I : IrSymbolOwner,
|
||||||
> getIrCallableSymbol(
|
> getIrCallableSymbol(
|
||||||
firSymbol: FS,
|
firSymbol: FS,
|
||||||
getCachedIrDeclaration: (F, (F) -> IdSignature?) -> I?,
|
dispatchReceiverLookupTag: ConeClassLikeLookupTag?,
|
||||||
|
getCachedIrDeclaration: (F, ConeClassLikeLookupTag?, (F) -> IdSignature?) -> I?,
|
||||||
createIrDeclaration: (IrDeclarationParent?, IrDeclarationOrigin) -> I,
|
createIrDeclaration: (IrDeclarationParent?, IrDeclarationOrigin) -> I,
|
||||||
createIrLazyDeclaration: (IdSignature, Fir2IrLazyClass, IrDeclarationOrigin) -> I,
|
createIrLazyDeclaration: (IdSignature, Fir2IrLazyClass, IrDeclarationOrigin) -> I,
|
||||||
): IrSymbol {
|
): IrSymbol {
|
||||||
val fir = firSymbol.fir as F
|
val fir = firSymbol.fir as F
|
||||||
val irParent by lazy { findIrParent(fir) }
|
val irParent by lazy { findIrParent(fir) }
|
||||||
val signature by lazy { signatureComposer.composeSignature(fir) }
|
val signature by lazy { signatureComposer.composeSignature(fir, dispatchReceiverLookupTag) }
|
||||||
synchronized(symbolTable.lock) {
|
synchronized(symbolTable.lock) {
|
||||||
getCachedIrDeclaration(fir) {
|
getCachedIrDeclaration(fir, dispatchReceiverLookupTag) {
|
||||||
// Parent calculation provokes declaration calculation for some members from IrBuiltIns
|
// Parent calculation provokes declaration calculation for some members from IrBuiltIns
|
||||||
@Suppress("UNUSED_EXPRESSION") irParent
|
@Suppress("UNUSED_EXPRESSION") irParent
|
||||||
signature
|
signature
|
||||||
|
|||||||
+2
-2
@@ -184,7 +184,7 @@ class FakeOverrideGenerator(
|
|||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
isLocal: Boolean,
|
isLocal: Boolean,
|
||||||
originalSymbol: FirCallableSymbol<*>,
|
originalSymbol: FirCallableSymbol<*>,
|
||||||
cachedIrDeclaration: (D, (D) -> IdSignature?) -> I?,
|
cachedIrDeclaration: (D, ConeClassLikeLookupTag?, (D) -> IdSignature?) -> I?,
|
||||||
createIrDeclaration: (D, irParent: IrClass, thisReceiverOwner: IrClass?, origin: IrDeclarationOrigin, isLocal: Boolean) -> I,
|
createIrDeclaration: (D, irParent: IrClass, thisReceiverOwner: IrClass?, origin: IrDeclarationOrigin, isLocal: Boolean) -> I,
|
||||||
createFakeOverrideSymbol: (D, S) -> S,
|
createFakeOverrideSymbol: (D, S) -> S,
|
||||||
baseSymbols: MutableMap<I, List<S>>,
|
baseSymbols: MutableMap<I, List<S>>,
|
||||||
@@ -227,7 +227,7 @@ class FakeOverrideGenerator(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val irDeclaration = cachedIrDeclaration(fakeOverrideFirDeclaration) {
|
val irDeclaration = cachedIrDeclaration(fakeOverrideFirDeclaration, null) {
|
||||||
// Sometimes we can have clashing here when FIR substitution/intersection override
|
// Sometimes we can have clashing here when FIR substitution/intersection override
|
||||||
// have the same signature.
|
// have the same signature.
|
||||||
// Now we avoid this problem by signature caching,
|
// Now we avoid this problem by signature caching,
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// !LANGUAGE: +InlineClasses
|
// !LANGUAGE: +InlineClasses
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
// FILE: Z.kt
|
// FILE: Z.kt
|
||||||
inline class Z(val x: Int)
|
inline class Z(val x: Int)
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// !LANGUAGE: +InlineClasses
|
// !LANGUAGE: +InlineClasses
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
// FILE: Z.kt
|
// FILE: Z.kt
|
||||||
inline class Z(val x: Int)
|
inline class Z(val x: Int)
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// !LANGUAGE: +InlineClasses
|
// !LANGUAGE: +InlineClasses
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
// FILE: Z.kt
|
// FILE: Z.kt
|
||||||
inline class Z(val x: Int)
|
inline class Z(val x: Int)
|
||||||
|
|||||||
Vendored
-1
@@ -1,5 +1,4 @@
|
|||||||
// !LANGUAGE: +InlineClasses
|
// !LANGUAGE: +InlineClasses
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// Completely incorrect bytecode - see `box/inlineClasses/toStringOfUnboxedNullable.kt`
|
// Completely incorrect bytecode - see `box/inlineClasses/toStringOfUnboxedNullable.kt`
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user