[FIR2IR] Generate f/o overridden symbol with FakeOverrideGenerator
#KT-43669 Fixed
This commit is contained in:
committed by
TeamCityServer
parent
91834ccf46
commit
9b0ada2b0f
+35
-38
@@ -149,46 +149,40 @@ class FakeOverrideGenerator(
|
|||||||
|
|
||||||
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
||||||
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
|
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
|
||||||
|
val baseDeclaration = when {
|
||||||
if (originalSymbol.fir.origin.fromSupertypes && originalSymbol.dispatchReceiverClassOrNull() == classLookupTag) {
|
originalSymbol.fir.origin.fromSupertypes && originalSymbol.dispatchReceiverClassOrNull() == classLookupTag -> {
|
||||||
// Substitution case
|
// Substitution case
|
||||||
// NB: see comment above about substituted function' parent
|
originalDeclaration
|
||||||
val irDeclaration = cachedIrDeclaration(originalDeclaration) {
|
}
|
||||||
// Sometimes we can have clashing here when FIR substitution/intersection override
|
originalDeclaration.allowsToHaveFakeOverrideIn(klass) -> {
|
||||||
// have the same signature.
|
// Trivial fake override case
|
||||||
// Now we avoid this problem by signature caching,
|
val fakeOverrideSymbol = createFakeOverrideSymbol(originalDeclaration, baseSymbol)
|
||||||
// so both FIR overrides correspond to one IR fake override
|
classifierStorage.preCacheTypeParameters(originalDeclaration)
|
||||||
signatureComposer.composeSignature(originalDeclaration)
|
fakeOverrideSymbol.fir
|
||||||
}?.takeIf { it.parent == irClass }
|
}
|
||||||
?: createIrDeclaration(
|
else -> {
|
||||||
originalDeclaration, irClass,
|
return
|
||||||
declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
}
|
||||||
origin,
|
}
|
||||||
isLocal
|
val irDeclaration = cachedIrDeclaration(baseDeclaration) {
|
||||||
)
|
// Sometimes we can have clashing here when FIR substitution/intersection override
|
||||||
irDeclaration.parent = irClass
|
// have the same signature.
|
||||||
baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classLookupTag)
|
// Now we avoid this problem by signature caching,
|
||||||
result += irDeclaration
|
// so both FIR overrides correspond to one IR fake override
|
||||||
} else if (originalDeclaration.allowsToHaveFakeOverrideIn(klass)) {
|
signatureComposer.composeSignature(baseDeclaration)
|
||||||
// Trivial fake override case
|
}?.takeIf { it.parent == irClass }
|
||||||
val fakeOverrideSymbol = createFakeOverrideSymbol(
|
?: createIrDeclaration(
|
||||||
originalDeclaration, baseSymbol
|
baseDeclaration,
|
||||||
)
|
irClass,
|
||||||
|
/* thisReceiverOwner = */ declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
||||||
classifierStorage.preCacheTypeParameters(originalDeclaration)
|
|
||||||
val irDeclaration = createIrDeclaration(
|
|
||||||
fakeOverrideSymbol.fir, irClass,
|
|
||||||
declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
|
||||||
origin,
|
origin,
|
||||||
isLocal
|
isLocal
|
||||||
)
|
)
|
||||||
if (containsErrorTypes(irDeclaration)) {
|
if (containsErrorTypes(irDeclaration)) {
|
||||||
return
|
return
|
||||||
}
|
|
||||||
irDeclaration.parent = irClass
|
|
||||||
baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classLookupTag)
|
|
||||||
result += irDeclaration
|
|
||||||
}
|
}
|
||||||
|
baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classLookupTag)
|
||||||
|
result += irDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified S : FirCallableSymbol<*>> computeBaseSymbols(
|
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>) {
|
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
|
||||||
when (declaration) {
|
when (declaration) {
|
||||||
is IrSimpleFunction -> {
|
is IrSimpleFunction -> {
|
||||||
val baseSymbols =
|
val baseSymbols = getOverriddenSymbols(declaration)!!
|
||||||
baseFunctionSymbols[declaration]!!.map { declarationStorage.getIrFunctionSymbol(it) as IrSimpleFunctionSymbol }
|
|
||||||
declaration.withFunction {
|
declaration.withFunction {
|
||||||
overriddenSymbols = baseSymbols
|
overriddenSymbols = baseSymbols
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ class Fir2IrLazySimpleFunction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override var overriddenSymbols: List<IrSimpleFunctionSymbol> by lazyVar {
|
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)
|
fir.generateOverriddenFunctionSymbols(firParent, session, scopeSession, declarationStorage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
@@ -435,6 +435,11 @@ public class FirCompileKotlinAgainstKotlinTestGenerated extends AbstractFirCompi
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
|
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")
|
@TestMetadata("LibraryProperty.kt")
|
||||||
public void testLibraryProperty() throws Exception {
|
public void testLibraryProperty() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Generated
+5
@@ -440,6 +440,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
|
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")
|
@TestMetadata("LibraryProperty.kt")
|
||||||
public void testLibraryProperty() throws Exception {
|
public void testLibraryProperty() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
|
||||||
|
|||||||
Generated
+5
@@ -435,6 +435,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
|
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")
|
@TestMetadata("LibraryProperty.kt")
|
||||||
public void testLibraryProperty() throws Exception {
|
public void testLibraryProperty() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
|
||||||
|
|||||||
+5
@@ -435,6 +435,11 @@ public class JvmIrAgainstOldBoxTestGenerated extends AbstractJvmIrAgainstOldBoxT
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
|
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")
|
@TestMetadata("LibraryProperty.kt")
|
||||||
public void testLibraryProperty() throws Exception {
|
public void testLibraryProperty() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
|
||||||
|
|||||||
+5
@@ -435,6 +435,11 @@ public class JvmOldAgainstIrBoxTestGenerated extends AbstractJvmOldAgainstIrBoxT
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/ExistingSymbolInFakeOverride.kt");
|
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")
|
@TestMetadata("LibraryProperty.kt")
|
||||||
public void testLibraryProperty() throws Exception {
|
public void testLibraryProperty() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/fir/LibraryProperty.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user