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.builtins.KotlinBuiltIns.*
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations 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.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
@@ -239,31 +240,63 @@ class Fir2IrDeclarationStorage(
} }
} }
is FirRegularClass -> { is FirRegularClass -> {
irClass.declarations += classifierStorage.createIrClass(declaration, irClass) val nestedExternalClass = classifierStorage.createIrClass(declaration, irClass)
addDeclarationsToExternalClass(declaration, nestedExternalClass)
irClass.declarations += nestedExternalClass
} }
else -> continue else -> continue
} }
} }
// TODO: better to refactor somehow so as to entirely reuse FakeOverrideGenerator's logic.
val allNames = regularClass.collectCallableNamesFromSupertypes(session) val allNames = regularClass.collectCallableNamesFromSupertypes(session)
for (name in allNames) { for (name in allNames) {
if (name in processedNames) continue if (name in processedNames) continue
processedNames += name processedNames += name
scope.processFunctionsByName(name) { functionSymbol -> scope.processFunctionsByName(name) { functionSymbol ->
if (functionSymbol is FirNamedFunctionSymbol) { if (functionSymbol is FirNamedFunctionSymbol) {
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideFunction( val originalFunction = functionSymbol.fir
session, functionSymbol.fir, functionSymbol, derivedClassId = regularClass.symbol.classId if (functionSymbol.isFakeOverride) {
) // Substitution case
classifierStorage.preCacheTypeParameters(functionSymbol.fir) val baseSymbol = functionSymbol.deepestOverriddenSymbol() as FirNamedFunctionSymbol
irClass.declarations += createIrFunction(fakeOverrideSymbol.fir, irClass) 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 -> scope.processPropertiesByName(name) { propertySymbol ->
if (propertySymbol is FirPropertySymbol) { if (propertySymbol is FirPropertySymbol) {
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideProperty( val originalProperty = propertySymbol.fir
session, propertySymbol.fir, propertySymbol, derivedClassId = regularClass.symbol.classId if (propertySymbol.isFakeOverride) {
) // Substitution case
classifierStorage.preCacheTypeParameters(propertySymbol.fir) val baseSymbol = propertySymbol.deepestOverriddenSymbol() as FirPropertySymbol
irClass.declarations += createIrProperty(fakeOverrideSymbol.fir, irClass) 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) 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 { private fun FirCallableMemberDeclaration<*>.allowsToHaveFakeOverrideIn(klass: FirClass<*>): Boolean {
if (!allowsToHaveFakeOverride) return false if (!allowsToHaveFakeOverride) return false
if (this.visibility != JavaVisibilities.PACKAGE_VISIBILITY) return true if (this.visibility != JavaVisibilities.PACKAGE_VISIBILITY) return true
@@ -138,7 +120,7 @@ internal class FakeOverrideGenerator(
origin = origin origin = origin
) )
declarations += irProperty.withProperty { declarations += irProperty.withProperty {
setOverriddenSymbolsForAccessors(originalProperty, firOverriddenSymbol = baseSymbol) setOverriddenSymbolsForAccessors(declarationStorage, originalProperty, firOverriddenSymbol = baseSymbol)
} }
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.allowsToHaveFakeOverrideIn(klass)) { } else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.allowsToHaveFakeOverrideIn(klass)) {
// Trivial fake override case // Trivial fake override case
@@ -167,12 +149,29 @@ internal class FakeOverrideGenerator(
return@processPropertiesByName return@processPropertiesByName
} }
declarations += irProperty.withProperty { 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
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: investigate should it be ran for JS or not // 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
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: investigate should it be ran for JS or not // TODO: investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: investigate should it be ran for JS or not // 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
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: investigate should it be ran for JS or not // TODO: investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// JVM_TARGET: 1.8 // JVM_TARGET: 1.8
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE // IGNORE_BACKEND: JS_IR, JS, NATIVE
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE // IGNORE_BACKEND: JS_IR, JS, NATIVE
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE // IGNORE_BACKEND: JS_IR, JS, NATIVE
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not // TODO: muted automatically, investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE // IGNORE_BACKEND: JS_IR, JS, NATIVE
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// KT-11447 Multifile declaration causes IAE: Method can not access a member of class // 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
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not // 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
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not // 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
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not // 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
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not // TODO: muted automatically, investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT