FIR2IR: Extract common parts in FakeOverrideGenerator
This commit is contained in:
+82
-87
@@ -11,6 +11,8 @@ import org.jetbrains.kotlin.fir.declarations.*
|
|||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -69,108 +71,101 @@ class FakeOverrideGenerator(
|
|||||||
processedCallableNames += name
|
processedCallableNames += name
|
||||||
val isLocal = klass !is FirRegularClass || klass.isLocal
|
val isLocal = klass !is FirRegularClass || klass.isLocal
|
||||||
useSiteMemberScope.processFunctionsByName(name) { functionSymbol ->
|
useSiteMemberScope.processFunctionsByName(name) { functionSymbol ->
|
||||||
if (functionSymbol is FirNamedFunctionSymbol) {
|
createFakeOverriddenIfNeeded(
|
||||||
val originalFunction = functionSymbol.fir
|
klass, this, isLocal, functionSymbol,
|
||||||
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
declarationStorage::getCachedIrFunction,
|
||||||
val baseSymbol = functionSymbol.deepestOverriddenSymbol() as FirNamedFunctionSymbol
|
declarationStorage::createIrFunction,
|
||||||
if (functionSymbol.isFakeOverride && functionSymbol.callableId.classId == klass.symbol.classId) {
|
createFakeOverrideSymbol = { firFunction, callableSymbol ->
|
||||||
// Substitution case
|
FirClassSubstitutionScope.createFakeOverrideFunction(
|
||||||
// NB: we can get same substituted FIR fake override in a different class, if it derives the same genetic type
|
session, firFunction, callableSymbol,
|
||||||
// open class Base<T> {
|
|
||||||
// fun foo(): T
|
|
||||||
// }
|
|
||||||
// class Derived1 : Base<String>() {}
|
|
||||||
// class Derived2 : Base<String>() {}
|
|
||||||
// That's why we must check parent during caching...
|
|
||||||
val irFunction = declarationStorage.getCachedIrFunction(originalFunction)?.takeIf { it.parent == this }
|
|
||||||
?: declarationStorage.createIrFunction(
|
|
||||||
originalFunction,
|
|
||||||
irParent = this,
|
|
||||||
thisReceiverOwner = declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
|
||||||
origin = origin,
|
|
||||||
isLocal = isLocal
|
|
||||||
)
|
|
||||||
// In fake overrides, parent logic is a bit specific, because
|
|
||||||
// parent of *original* function (base class) is used for dispatch receiver,
|
|
||||||
// but fake override itself uses parent from its containing (derived) class
|
|
||||||
irFunction.parent = this
|
|
||||||
baseFunctionSymbols[irFunction] = baseSymbol
|
|
||||||
result += irFunction
|
|
||||||
} else if (originalFunction.allowsToHaveFakeOverrideIn(klass)) {
|
|
||||||
// Trivial fake override case
|
|
||||||
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideFunction(
|
|
||||||
session, originalFunction, baseSymbol,
|
|
||||||
derivedClassId = klass.symbol.classId,
|
derivedClassId = klass.symbol.classId,
|
||||||
isExpect = (klass as? FirRegularClass)?.isExpect == true
|
isExpect = (klass as? FirRegularClass)?.isExpect == true
|
||||||
)
|
)
|
||||||
val fakeOverrideFunction = fakeOverrideSymbol.fir
|
},
|
||||||
|
baseFunctionSymbols,
|
||||||
classifierStorage.preCacheTypeParameters(originalFunction)
|
result,
|
||||||
val irFunction = declarationStorage.createIrFunction(
|
containsErrorTypes = { irFunction ->
|
||||||
fakeOverrideFunction,
|
irFunction.returnType.containsErrorType() || irFunction.valueParameters.any { it.type.containsErrorType() }
|
||||||
irParent = this,
|
|
||||||
thisReceiverOwner = declarationStorage.findIrParent(originalFunction) as? IrClass,
|
|
||||||
origin = origin,
|
|
||||||
isLocal = isLocal
|
|
||||||
)
|
|
||||||
if (irFunction.returnType.containsErrorType() || irFunction.valueParameters.any { it.type.containsErrorType() }) {
|
|
||||||
return@processFunctionsByName
|
|
||||||
}
|
|
||||||
irFunction.parent = this
|
|
||||||
baseFunctionSymbols[irFunction] = baseSymbol
|
|
||||||
result += irFunction
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
useSiteMemberScope.processPropertiesByName(name) { propertySymbol ->
|
useSiteMemberScope.processPropertiesByName(name) { propertySymbol ->
|
||||||
if (propertySymbol is FirPropertySymbol) {
|
createFakeOverriddenIfNeeded(
|
||||||
val originalProperty = propertySymbol.fir
|
klass, this, isLocal, propertySymbol,
|
||||||
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
declarationStorage::getCachedIrProperty,
|
||||||
val baseSymbol = propertySymbol.deepestOverriddenSymbol() as FirPropertySymbol
|
declarationStorage::createIrProperty,
|
||||||
if (propertySymbol.isFakeOverride && propertySymbol.callableId.classId == klass.symbol.classId) {
|
createFakeOverrideSymbol = { firProperty, callableSymbol ->
|
||||||
// Substitution case
|
FirClassSubstitutionScope.createFakeOverrideProperty(
|
||||||
// NB: see comment above about substituted function' parent
|
session, firProperty, callableSymbol,
|
||||||
val irProperty = declarationStorage.getCachedIrProperty(originalProperty)?.takeIf { it.parent == this }
|
|
||||||
?: declarationStorage.createIrProperty(
|
|
||||||
originalProperty, irParent = this,
|
|
||||||
thisReceiverOwner = declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
|
||||||
origin = origin,
|
|
||||||
isLocal = isLocal
|
|
||||||
)
|
|
||||||
irProperty.parent = this
|
|
||||||
basePropertySymbols[irProperty] = baseSymbol
|
|
||||||
result += irProperty
|
|
||||||
} else if (originalProperty.allowsToHaveFakeOverrideIn(klass)) {
|
|
||||||
// Trivial fake override case
|
|
||||||
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideProperty(
|
|
||||||
session, originalProperty, baseSymbol,
|
|
||||||
derivedClassId = klass.symbol.classId,
|
derivedClassId = klass.symbol.classId,
|
||||||
isExpect = (klass as? FirRegularClass)?.isExpect == true
|
isExpect = (klass as? FirRegularClass)?.isExpect == true
|
||||||
)
|
)
|
||||||
val fakeOverrideProperty = fakeOverrideSymbol.fir
|
},
|
||||||
|
basePropertySymbols,
|
||||||
classifierStorage.preCacheTypeParameters(originalProperty)
|
result,
|
||||||
val irProperty = declarationStorage.createIrProperty(
|
containsErrorTypes = { irProperty ->
|
||||||
fakeOverrideProperty, irParent = this,
|
irProperty.backingField?.type?.containsErrorType() == true ||
|
||||||
thisReceiverOwner = declarationStorage.findIrParent(originalProperty) as? IrClass,
|
irProperty.getter?.returnType?.containsErrorType() == true
|
||||||
origin = origin,
|
|
||||||
isLocal = isLocal
|
|
||||||
)
|
|
||||||
if (irProperty.backingField?.type?.containsErrorType() == true ||
|
|
||||||
irProperty.getter?.returnType?.containsErrorType() == true
|
|
||||||
) {
|
|
||||||
return@processPropertiesByName
|
|
||||||
}
|
|
||||||
irProperty.parent = this
|
|
||||||
basePropertySymbols[irProperty] = baseSymbol
|
|
||||||
result += irProperty
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun <reified D : FirCallableMemberDeclaration<D>, reified S, reified I : IrDeclaration> createFakeOverriddenIfNeeded(
|
||||||
|
klass: FirClass<*>,
|
||||||
|
irClass: IrClass,
|
||||||
|
isLocal: Boolean,
|
||||||
|
originalSymbol: FirCallableSymbol<*>,
|
||||||
|
cachedIrDeclaration: (D) -> I?,
|
||||||
|
createIrDeclaration: (D, irParent: IrClass, thisReceiverOwner: IrClass?, origin: IrDeclarationOrigin, isLocal: Boolean) -> I,
|
||||||
|
createFakeOverrideSymbol: (D, S) -> S,
|
||||||
|
baseSymbols: MutableMap<I, S>,
|
||||||
|
result: MutableList<in I>,
|
||||||
|
containsErrorTypes: (I) -> Boolean
|
||||||
|
) where S : FirCallableSymbol<D>, S : PossiblyFirFakeOverrideSymbol<D, S> {
|
||||||
|
if (originalSymbol !is S) return
|
||||||
|
val originalDeclaration = originalSymbol.fir
|
||||||
|
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
||||||
|
val baseSymbol = originalSymbol.deepestOverriddenSymbol() as S
|
||||||
|
if (originalSymbol.isFakeOverride && originalSymbol.callableId.classId == klass.symbol.classId) {
|
||||||
|
// Substitution case
|
||||||
|
// NB: see comment above about substituted function' parent
|
||||||
|
val irDeclaration = cachedIrDeclaration(originalDeclaration)?.takeIf { it.parent == irClass }
|
||||||
|
?: createIrDeclaration(
|
||||||
|
originalDeclaration, irClass,
|
||||||
|
declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
||||||
|
origin,
|
||||||
|
isLocal
|
||||||
|
)
|
||||||
|
irDeclaration.parent = irClass
|
||||||
|
baseSymbols[irDeclaration] = baseSymbol
|
||||||
|
result += irDeclaration
|
||||||
|
} else if (originalDeclaration.allowsToHaveFakeOverrideIn(klass)) {
|
||||||
|
// Trivial fake override case
|
||||||
|
val fakeOverrideSymbol = createFakeOverrideSymbol(
|
||||||
|
originalDeclaration, baseSymbol
|
||||||
|
)
|
||||||
|
|
||||||
|
classifierStorage.preCacheTypeParameters(originalDeclaration)
|
||||||
|
val irDeclaration = createIrDeclaration(
|
||||||
|
fakeOverrideSymbol.fir, irClass,
|
||||||
|
declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
||||||
|
origin,
|
||||||
|
isLocal
|
||||||
|
)
|
||||||
|
if (containsErrorTypes(irDeclaration)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
irDeclaration.parent = irClass
|
||||||
|
baseSymbols[irDeclaration] = baseSymbol
|
||||||
|
result += irDeclaration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun bindOverriddenSymbols(declarations: List<IrDeclaration>) {
|
fun bindOverriddenSymbols(declarations: List<IrDeclaration>) {
|
||||||
for (declaration in declarations) {
|
for (declaration in declarations) {
|
||||||
if (declaration.origin != IrDeclarationOrigin.FAKE_OVERRIDE) continue
|
if (declaration.origin != IrDeclarationOrigin.FAKE_OVERRIDE) continue
|
||||||
|
|||||||
Reference in New Issue
Block a user