[FIR2IR] Generate f/o overridden symbol with FakeOverrideGenerator

#KT-43669 Fixed
This commit is contained in:
Mikhail Glukhikh
2020-11-30 15:31:40 +03:00
committed by TeamCityServer
parent 91834ccf46
commit 9b0ada2b0f
8 changed files with 162 additions and 38 deletions
@@ -149,46 +149,40 @@ class FakeOverrideGenerator(
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
if (originalSymbol.fir.origin.fromSupertypes && originalSymbol.dispatchReceiverClassOrNull() == classLookupTag) {
// Substitution case
// NB: see comment above about substituted function' parent
val irDeclaration = cachedIrDeclaration(originalDeclaration) {
// Sometimes we can have clashing here when FIR substitution/intersection override
// have the same signature.
// Now we avoid this problem by signature caching,
// so both FIR overrides correspond to one IR fake override
signatureComposer.composeSignature(originalDeclaration)
}?.takeIf { it.parent == irClass }
?: createIrDeclaration(
originalDeclaration, irClass,
declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
origin,
isLocal
)
irDeclaration.parent = irClass
baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classLookupTag)
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,
val baseDeclaration = when {
originalSymbol.fir.origin.fromSupertypes && originalSymbol.dispatchReceiverClassOrNull() == classLookupTag -> {
// Substitution case
originalDeclaration
}
originalDeclaration.allowsToHaveFakeOverrideIn(klass) -> {
// Trivial fake override case
val fakeOverrideSymbol = createFakeOverrideSymbol(originalDeclaration, baseSymbol)
classifierStorage.preCacheTypeParameters(originalDeclaration)
fakeOverrideSymbol.fir
}
else -> {
return
}
}
val irDeclaration = cachedIrDeclaration(baseDeclaration) {
// Sometimes we can have clashing here when FIR substitution/intersection override
// have the same signature.
// Now we avoid this problem by signature caching,
// so both FIR overrides correspond to one IR fake override
signatureComposer.composeSignature(baseDeclaration)
}?.takeIf { it.parent == irClass }
?: createIrDeclaration(
baseDeclaration,
irClass,
/* thisReceiverOwner = */ declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
origin,
isLocal
)
if (containsErrorTypes(irDeclaration)) {
return
}
irDeclaration.parent = irClass
baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classLookupTag)
result += irDeclaration
if (containsErrorTypes(irDeclaration)) {
return
}
baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classLookupTag)
result += irDeclaration
}
private inline fun <reified S : FirCallableSymbol<*>> computeBaseSymbols(
@@ -208,13 +202,16 @@ class FakeOverrideGenerator(
}
}
internal fun getOverriddenSymbols(function: IrSimpleFunction): List<IrSimpleFunctionSymbol>? {
return baseFunctionSymbols[function]?.map { declarationStorage.getIrFunctionSymbol(it) as IrSimpleFunctionSymbol }
}
fun bindOverriddenSymbols(declarations: List<IrDeclaration>) {
for (declaration in declarations) {
if (declaration.origin != IrDeclarationOrigin.FAKE_OVERRIDE) continue
when (declaration) {
is IrSimpleFunction -> {
val baseSymbols =
baseFunctionSymbols[declaration]!!.map { declarationStorage.getIrFunctionSymbol(it) as IrSimpleFunctionSymbol }
val baseSymbols = getOverriddenSymbols(declaration)!!
declaration.withFunction {
overriddenSymbols = baseSymbols
}
@@ -67,6 +67,11 @@ class Fir2IrLazySimpleFunction(
}
override var overriddenSymbols: List<IrSimpleFunctionSymbol> by lazyVar {
val parent = parent
if (isFakeOverride && parent is Fir2IrLazyClass) {
parent.declarations
fakeOverrideGenerator.getOverriddenSymbols(this)?.let { return@lazyVar it }
}
fir.generateOverriddenFunctionSymbols(firParent, session, scopeSession, declarationStorage)
}
@@ -435,6 +435,11 @@ public class FirCompileKotlinAgainstKotlinTestGenerated extends AbstractFirCompi
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
}
@TestMetadata("IrConstAcceptMultiModule.kt")
public void testIrConstAcceptMultiModule() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/IrConstAcceptMultiModule.kt");
}
@TestMetadata("LibraryProperty.kt")
public void testLibraryProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
@@ -0,0 +1,97 @@
// TARGET_BACKEND: JVM
// FILE: A.kt
// WITH_RUNTIME
abstract class IrConst<T> : IrExpression(), IrExpressionWithCopy {
abstract val kind: IrConstKind<T>
abstract val value: T
abstract override fun copy(): IrConst<T>
abstract fun copyWithOffsets(startOffset: Int, endOffset: Int): IrConst<T>
}
sealed class IrConstKind<T>(val asString: kotlin.String) {
@Suppress("UNCHECKED_CAST")
fun valueOf(aConst: IrConst<*>) =
(aConst as IrConst<T>).value
object Null : IrConstKind<Nothing?>("Null")
object Boolean : IrConstKind<kotlin.Boolean>("Boolean")
object Char : IrConstKind<kotlin.Char>("Char")
object Byte : IrConstKind<kotlin.Byte>("Byte")
object Short : IrConstKind<kotlin.Short>("Short")
object Int : IrConstKind<kotlin.Int>("Int")
object Long : IrConstKind<kotlin.Long>("Long")
object String : IrConstKind<kotlin.String>("String")
object Float : IrConstKind<kotlin.Float>("Float")
object Double : IrConstKind<kotlin.Double>("Double")
override fun toString() = asString
}
interface IrType
abstract class IrExpression : IrElementBase(), IrStatement, IrVarargElement, IrAttributeContainer {
@Suppress("LeakingThis")
override var attributeOwnerId: IrAttributeContainer = this
abstract var type: IrType
override fun <D> transform(transformer: IrElementTransformer<D>, data: D): IrExpression =
accept(transformer, data) as IrExpression
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
// No children by default
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
// No children by default
}
}
interface IrExpressionWithCopy {
fun copy(): IrExpression
}
interface IrAttributeContainer : IrElement {
var attributeOwnerId: IrAttributeContainer
}
abstract class IrElementBase : IrElement
interface IrStatement : IrElement
interface IrVarargElement : IrElement
interface IrElement {
val startOffset: Int
val endOffset: Int
fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R
fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D): Unit
fun <D> transform(transformer: IrElementTransformer<D>, data: D): IrElement =
accept(transformer, data)
fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D): Unit
}
interface IrElementVisitor<out R, in D>
interface IrElementTransformer<in D> : IrElementVisitor<IrElement, D>
// FILE: B.kt
fun foo(cases: Collection<IrConst<*>>, exprTransformer: IrElementTransformer<Any>, context: Any) {
cases.map {
it.accept(exprTransformer, context)
}
}
fun box(): String {
return "OK"
}
@@ -440,6 +440,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
}
@TestMetadata("IrConstAcceptMultiModule.kt")
public void testIrConstAcceptMultiModule() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/IrConstAcceptMultiModule.kt");
}
@TestMetadata("LibraryProperty.kt")
public void testLibraryProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
@@ -435,6 +435,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
}
@TestMetadata("IrConstAcceptMultiModule.kt")
public void testIrConstAcceptMultiModule() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/IrConstAcceptMultiModule.kt");
}
@TestMetadata("LibraryProperty.kt")
public void testLibraryProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
@@ -435,6 +435,11 @@ public class JvmIrAgainstOldBoxTestGenerated extends AbstractJvmIrAgainstOldBoxT
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
}
@TestMetadata("IrConstAcceptMultiModule.kt")
public void testIrConstAcceptMultiModule() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/IrConstAcceptMultiModule.kt");
}
@TestMetadata("LibraryProperty.kt")
public void testLibraryProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
@@ -435,6 +435,11 @@ public class JvmOldAgainstIrBoxTestGenerated extends AbstractJvmOldAgainstIrBoxT
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
}
@TestMetadata("IrConstAcceptMultiModule.kt")
public void testIrConstAcceptMultiModule() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/IrConstAcceptMultiModule.kt");
}
@TestMetadata("LibraryProperty.kt")
public void testLibraryProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");