FIR2IR: distinguish substitution case when adding external fake overrides

This commit is contained in:
Jinseong Jeon
2020-06-02 09:34:03 +03:00
committed by Mikhail Glukhikh
parent 538535c3b7
commit ba1172b3ad
24 changed files with 64 additions and 54 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.fir.backend.generators.setOverriddenSymbolsForAccessors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
@@ -239,31 +240,63 @@ class Fir2IrDeclarationStorage(
}
}
is FirRegularClass -> {
irClass.declarations += classifierStorage.createIrClass(declaration, irClass)
val nestedExternalClass = classifierStorage.createIrClass(declaration, irClass)
addDeclarationsToExternalClass(declaration, nestedExternalClass)
irClass.declarations += nestedExternalClass
}
else -> continue
}
}
// TODO: better to refactor somehow so as to entirely reuse FakeOverrideGenerator's logic.
val allNames = regularClass.collectCallableNamesFromSupertypes(session)
for (name in allNames) {
if (name in processedNames) continue
processedNames += name
scope.processFunctionsByName(name) { functionSymbol ->
if (functionSymbol is FirNamedFunctionSymbol) {
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideFunction(
session, functionSymbol.fir, functionSymbol, derivedClassId = regularClass.symbol.classId
)
classifierStorage.preCacheTypeParameters(functionSymbol.fir)
irClass.declarations += createIrFunction(fakeOverrideSymbol.fir, irClass)
val originalFunction = functionSymbol.fir
if (functionSymbol.isFakeOverride) {
// Substitution case
val baseSymbol = functionSymbol.deepestOverriddenSymbol() as FirNamedFunctionSymbol
val irFunction = createIrFunction(
originalFunction, irParent = irClass,
thisReceiverOwner = findIrParent(baseSymbol.fir) as? IrClass,
origin = IrDeclarationOrigin.FAKE_OVERRIDE
)
val overriddenSymbol = getIrFunctionSymbol(baseSymbol) as IrSimpleFunctionSymbol
irClass.declarations += irFunction.apply {
overriddenSymbols = listOf(overriddenSymbol)
}
} else {
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideFunction(
session, originalFunction, functionSymbol, derivedClassId = regularClass.symbol.classId
)
classifierStorage.preCacheTypeParameters(functionSymbol.fir)
irClass.declarations += createIrFunction(fakeOverrideSymbol.fir, irClass)
}
}
}
scope.processPropertiesByName(name) { propertySymbol ->
if (propertySymbol is FirPropertySymbol) {
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideProperty(
session, propertySymbol.fir, propertySymbol, derivedClassId = regularClass.symbol.classId
)
classifierStorage.preCacheTypeParameters(propertySymbol.fir)
irClass.declarations += createIrProperty(fakeOverrideSymbol.fir, irClass)
val originalProperty = propertySymbol.fir
if (propertySymbol.isFakeOverride) {
// Substitution case
val baseSymbol = propertySymbol.deepestOverriddenSymbol() as FirPropertySymbol
val irProperty = createIrProperty(
originalProperty, irParent = irClass,
thisReceiverOwner = findIrParent(baseSymbol.fir) as? IrClass,
origin = IrDeclarationOrigin.FAKE_OVERRIDE
)
irClass.declarations += irProperty.apply {
setOverriddenSymbolsForAccessors(declarationStorage, originalProperty, baseSymbol)
}
} else {
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideProperty(
session, originalProperty, propertySymbol, derivedClassId = regularClass.symbol.classId
)
classifierStorage.preCacheTypeParameters(propertySymbol.fir)
irClass.declarations += createIrProperty(fakeOverrideSymbol.fir, irClass)
}
}
}
}
@@ -41,24 +41,6 @@ internal class FakeOverrideGenerator(
return conversionScope.withProperty(conversionScope.applyParentFromStackTo(this), f)
}
private fun IrProperty.setOverriddenSymbolsForAccessors(
property: FirProperty,
firOverriddenSymbol: FirPropertySymbol
): IrProperty {
val irSymbol = declarationStorage.getIrPropertyOrFieldSymbol(firOverriddenSymbol) as? IrPropertySymbol ?: return this
val overriddenProperty = irSymbol.owner
getter?.apply {
overriddenProperty.getter?.symbol?.let { overriddenSymbols = listOf(it) }
}
if (property.isVar) {
setter?.apply {
overriddenProperty.setter?.symbol?.let { overriddenSymbols = listOf(it) }
}
}
return this
}
private fun FirCallableMemberDeclaration<*>.allowsToHaveFakeOverrideIn(klass: FirClass<*>): Boolean {
if (!allowsToHaveFakeOverride) return false
if (this.visibility != JavaVisibilities.PACKAGE_VISIBILITY) return true
@@ -138,7 +120,7 @@ internal class FakeOverrideGenerator(
origin = origin
)
declarations += irProperty.withProperty {
setOverriddenSymbolsForAccessors(originalProperty, firOverriddenSymbol = baseSymbol)
setOverriddenSymbolsForAccessors(declarationStorage, originalProperty, firOverriddenSymbol = baseSymbol)
}
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.allowsToHaveFakeOverrideIn(klass)) {
// Trivial fake override case
@@ -167,12 +149,29 @@ internal class FakeOverrideGenerator(
return@processPropertiesByName
}
declarations += irProperty.withProperty {
setOverriddenSymbolsForAccessors(fakeOverrideProperty, firOverriddenSymbol = propertySymbol)
setOverriddenSymbolsForAccessors(declarationStorage, fakeOverrideProperty, firOverriddenSymbol = propertySymbol)
}
}
}
}
}
}
}
internal fun IrProperty.setOverriddenSymbolsForAccessors(
declarationStorage: Fir2IrDeclarationStorage,
property: FirProperty,
firOverriddenSymbol: FirPropertySymbol
): IrProperty {
val irSymbol = declarationStorage.getIrPropertyOrFieldSymbol(firOverriddenSymbol) as? IrPropertySymbol ?: return this
val overriddenProperty = irSymbol.owner
getter?.apply {
overriddenProperty.getter?.symbol?.let { overriddenSymbols = listOf(it) }
}
if (property.isVar) {
setter?.apply {
overriddenProperty.setter?.symbol?.let { overriddenSymbols = listOf(it) }
}
}
return this
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE
// IGNORE_BACKEND: JS_IR_ES6
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE
// IGNORE_BACKEND: JS_IR_ES6
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE
// IGNORE_BACKEND: JS_IR_ES6
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE
// IGNORE_BACKEND: JS_IR_ES6
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// KT-11447 Multifile declaration causes IAE: Method can not access a member of class
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT