[FIR2IR] Properly create FIR f/o for lazy IR f/o
```kotlin
interface A {
fun foo() // (1)
}
interface B : A {
// f/o fun foo() // (2)
}
```
In previous commits it was forgotten to create new FIR declarations for
IR fake-overrides, which led to the situation when `IR lazy functions
of `(1)` and `(2)` both contained fir of function (1) as their base
declaration
It seems this change fixed some cases from KT-42020
This commit is contained in:
committed by
Space Team
parent
8ebb412705
commit
89b98ef784
+23
-4
@@ -615,11 +615,16 @@ class Fir2IrDeclarationStorage(
|
||||
val symbols = createPropertySymbols(signature, property, fakeOverrideOwnerLookupTag)
|
||||
val irParent = findIrParent(property, fakeOverrideOwnerLookupTag)
|
||||
if (irParent?.isExternalParent() == true) {
|
||||
val firForLazyProperty = calculateFirForLazyDeclaration(
|
||||
property, fakeOverrideOwnerLookupTag, irParent,
|
||||
fakeOverrideGenerator::createFirPropertyFakeOverrideIfNeeded
|
||||
)
|
||||
|
||||
callablesGenerator.createIrProperty(
|
||||
property,
|
||||
firForLazyProperty,
|
||||
irParent,
|
||||
symbols,
|
||||
predefinedOrigin = property.computeExternalOrigin(),
|
||||
predefinedOrigin = firForLazyProperty.computeExternalOrigin(),
|
||||
allowLazyDeclarationsCreation = true
|
||||
).also {
|
||||
check(it is Fir2IrLazyProperty)
|
||||
@@ -991,13 +996,17 @@ class Fir2IrDeclarationStorage(
|
||||
if (function is FirSimpleFunction && !isLocal) {
|
||||
val irParent = findIrParent(function, fakeOverrideOwnerLookupTag)
|
||||
if (irParent?.isExternalParent() == true) {
|
||||
val firForLazyFunction = calculateFirForLazyDeclaration(
|
||||
function, fakeOverrideOwnerLookupTag, irParent,
|
||||
fakeOverrideGenerator::createFirFunctionFakeOverrideIfNeeded
|
||||
)
|
||||
// Return value is not used here, because creation of IR declaration binds it to the corresponding symbol
|
||||
// And all we want here is to bind symbol for lazy declaration
|
||||
callablesGenerator.createIrFunction(
|
||||
function,
|
||||
firForLazyFunction,
|
||||
irParent,
|
||||
symbol,
|
||||
predefinedOrigin = function.computeExternalOrigin(),
|
||||
predefinedOrigin = firForLazyFunction.computeExternalOrigin(),
|
||||
isLocal = false,
|
||||
fakeOverrideOwnerLookupTag,
|
||||
allowLazyDeclarationsCreation = true
|
||||
@@ -1131,6 +1140,16 @@ class Fir2IrDeclarationStorage(
|
||||
return null
|
||||
}
|
||||
|
||||
private inline fun <T : FirCallableDeclaration> calculateFirForLazyDeclaration(
|
||||
originalDeclaration: T,
|
||||
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?,
|
||||
irParent: IrDeclarationParent,
|
||||
createFakeOverrideIfNeeded: (T, ConeClassLikeLookupTag, IrClass) -> T?
|
||||
): T {
|
||||
if (irParent !is IrClass || fakeOverrideOwnerLookupTag == null) return originalDeclaration
|
||||
return createFakeOverrideIfNeeded(originalDeclaration, fakeOverrideOwnerLookupTag, irParent) ?: originalDeclaration
|
||||
}
|
||||
|
||||
private fun generateLazyFakeOverrides(name: Name, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?) {
|
||||
val firClassSymbol = fakeOverrideOwnerLookupTag?.toSymbol(session) as? FirClassSymbol
|
||||
if (firClassSymbol != null) {
|
||||
|
||||
@@ -118,7 +118,11 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
|
||||
scope.processFunctionsByName(lastName) { functionSymbol ->
|
||||
val dispatchReceiverClassId = (functionSymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
|
||||
val function = if (dispatchReceiverClassId != null && dispatchReceiverClassId != classId) {
|
||||
fakeOverrideGenerator.createFirFunctionFakeOverride(firClass, parentClass, functionSymbol, scope)!!.first
|
||||
fakeOverrideGenerator.createFirFunctionFakeOverrideIfNeeded(
|
||||
functionSymbol.fir,
|
||||
firClass.symbol.toLookupTag(),
|
||||
parentClass
|
||||
)!!
|
||||
} else functionSymbol.fir
|
||||
functions.add(function)
|
||||
}
|
||||
@@ -135,7 +139,11 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
|
||||
propertySymbol as FirPropertySymbol
|
||||
val dispatchReceiverClassId = (propertySymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
|
||||
val property = if (dispatchReceiverClassId != null && dispatchReceiverClassId != classId) {
|
||||
fakeOverrideGenerator.createFirPropertyFakeOverride(firClass, parentClass, propertySymbol, scope)!!.first
|
||||
fakeOverrideGenerator.createFirPropertyFakeOverrideIfNeeded(
|
||||
propertySymbol.fir,
|
||||
firClass.symbol.toLookupTag(),
|
||||
parentClass
|
||||
)!!
|
||||
} else propertySymbol.fir
|
||||
properties.add(property)
|
||||
}
|
||||
|
||||
+46
-53
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.isRealOwnerOf
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
||||
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FakeOverrideGenerator(
|
||||
@@ -314,80 +316,71 @@ class FakeOverrideGenerator(
|
||||
result?.add(owner)
|
||||
}
|
||||
|
||||
private inline fun <D : FirCallableDeclaration, reified S : FirCallableSymbol<D>> createFirFakeOverride(
|
||||
klass: FirClass,
|
||||
private inline fun <D : FirCallableDeclaration, reified S : FirCallableSymbol<D>> createFirFakeOverrideIfNeeded(
|
||||
dispatchReceiverLookupTag: ConeClassLikeLookupTag,
|
||||
irClass: IrClass,
|
||||
originalSymbol: S,
|
||||
createFakeOverrideSymbol: (firDeclaration: D, baseSymbol: S) -> S,
|
||||
computeDirectOverridden: FirTypeScope.(S) -> List<S>,
|
||||
scope: FirTypeScope,
|
||||
): Pair<D, List<S>>? {
|
||||
val classLookupTag = klass.symbol.toLookupTag()
|
||||
createFakeOverrideSymbol: (firDeclaration: D) -> S,
|
||||
): D? {
|
||||
val originalDeclaration = originalSymbol.fir
|
||||
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
|
||||
return when {
|
||||
originalSymbol.shouldHaveComputedBaseSymbolsForClass(classLookupTag) -> {
|
||||
// Substitution or intersection case
|
||||
// We have already a FIR declaration for such fake override
|
||||
originalDeclaration to computeBaseSymbols(
|
||||
originalSymbol,
|
||||
computeDirectOverridden,
|
||||
scope, classLookupTag
|
||||
)
|
||||
}
|
||||
originalSymbol.containingClassLookupTag() == dispatchReceiverLookupTag -> null
|
||||
|
||||
originalDeclaration.allowsToHaveFakeOverride -> {
|
||||
// Trivial fake override case
|
||||
// We've got no relevant declaration in FIR world for such a fake override in current class, thus we're creating it here
|
||||
val fakeOverrideSymbol = createFakeOverrideSymbol(originalDeclaration, baseSymbol)
|
||||
val fakeOverrideSymbol = createFakeOverrideSymbol(originalDeclaration)
|
||||
declarationStorage.saveFakeOverrideInClass(irClass, originalDeclaration, fakeOverrideSymbol.fir)
|
||||
classifierStorage.preCacheTypeParameters(originalDeclaration, irClass.symbol)
|
||||
fakeOverrideSymbol.fir to listOf(originalSymbol)
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
fakeOverrideSymbol.fir
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
internal fun createFirFunctionFakeOverride(
|
||||
klass: FirClass,
|
||||
internal fun createFirFunctionFakeOverrideIfNeeded(
|
||||
originalFunction: FirSimpleFunction,
|
||||
dispatchReceiverLookupTag: ConeClassLikeLookupTag,
|
||||
irClass: IrClass,
|
||||
originalSymbol: FirNamedFunctionSymbol,
|
||||
scope: FirTypeScope
|
||||
) = createFirFakeOverride(
|
||||
klass, irClass, originalSymbol,
|
||||
createFakeOverrideSymbol = { firFunction, callableSymbol ->
|
||||
): FirSimpleFunction? {
|
||||
val originalSymbol = originalFunction.symbol
|
||||
return createFirFakeOverrideIfNeeded(
|
||||
dispatchReceiverLookupTag, irClass, originalSymbol
|
||||
) { firFunction ->
|
||||
val containingClass = dispatchReceiverLookupTag.toFirRegularClass(session)!!
|
||||
FirFakeOverrideGenerator.createSubstitutionOverrideFunction(
|
||||
session, callableSymbol, firFunction,
|
||||
derivedClassLookupTag = klass.symbol.toLookupTag(),
|
||||
newDispatchReceiverType = klass.defaultType(),
|
||||
session,
|
||||
FirNamedFunctionSymbol(CallableId(containingClass.symbol.classId, originalSymbol.callableId.callableName)),
|
||||
firFunction,
|
||||
derivedClassLookupTag = dispatchReceiverLookupTag,
|
||||
newDispatchReceiverType = containingClass.defaultType(),
|
||||
origin = FirDeclarationOrigin.SubstitutionOverride.DeclarationSite,
|
||||
isExpect = (klass as? FirRegularClass)?.isExpect == true || firFunction.isExpect
|
||||
isExpect = containingClass.isExpect || firFunction.isExpect
|
||||
)
|
||||
},
|
||||
computeDirectOverridden = FirTypeScope::getDirectOverriddenFunctions,
|
||||
scope
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun createFirPropertyFakeOverride(
|
||||
klass: FirClass,
|
||||
internal fun createFirPropertyFakeOverrideIfNeeded(
|
||||
originalProperty: FirProperty,
|
||||
dispatchReceiverLookupTag: ConeClassLikeLookupTag,
|
||||
irClass: IrClass,
|
||||
originalSymbol: FirPropertySymbol,
|
||||
scope: FirTypeScope
|
||||
) = createFirFakeOverride(
|
||||
klass, irClass, originalSymbol,
|
||||
createFakeOverrideSymbol = { firProperty, callableSymbol ->
|
||||
): FirProperty? {
|
||||
val originalSymbol = originalProperty.symbol
|
||||
return createFirFakeOverrideIfNeeded(
|
||||
dispatchReceiverLookupTag, irClass, originalSymbol
|
||||
) { firProperty ->
|
||||
val containingClass = dispatchReceiverLookupTag.toFirRegularClass(session)!!
|
||||
FirFakeOverrideGenerator.createSubstitutionOverrideProperty(
|
||||
session, callableSymbol, firProperty,
|
||||
derivedClassLookupTag = klass.symbol.toLookupTag(),
|
||||
newDispatchReceiverType = klass.defaultType(),
|
||||
session,
|
||||
FirPropertySymbol(CallableId(containingClass.symbol.classId, originalSymbol.callableId.callableName)),
|
||||
firProperty,
|
||||
derivedClassLookupTag = dispatchReceiverLookupTag,
|
||||
newDispatchReceiverType = containingClass.defaultType(),
|
||||
origin = FirDeclarationOrigin.SubstitutionOverride.DeclarationSite,
|
||||
isExpect = (klass as? FirRegularClass)?.isExpect == true || firProperty.isExpect
|
||||
isExpect = containingClass.isExpect || firProperty.isExpect
|
||||
)
|
||||
},
|
||||
computeDirectOverridden = FirTypeScope::getDirectOverriddenProperties,
|
||||
scope
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified S : FirCallableSymbol<*>> computeBaseSymbols(
|
||||
symbol: S,
|
||||
|
||||
+4
-3
@@ -1,7 +1,8 @@
|
||||
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
|
||||
// KT-59609
|
||||
// IGNORE_BACKEND_K2: JS_IR
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// FIR status: Validation failed. TODO decide if we want to fix KT-42020 for FIR as well
|
||||
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION
|
||||
// Reason: KT-42020
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: a.kt
|
||||
package a
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
|
||||
// FIR status: validation failed. TODO decide if we want to fix KT-42020 for FIR as well
|
||||
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION
|
||||
// Reason: KT-42020
|
||||
|
||||
open class Base<T> {
|
||||
fun foo(x: T) = "x:$x"
|
||||
@@ -26,4 +26,4 @@ fun box(): String {
|
||||
throw Exception("test4: $test4")
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -7,8 +7,6 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// IGNORE_BACKEND_K2: NATIVE, JS_IR
|
||||
|
||||
// FIR status: validation failed. TODO decide if we want to fix KT-42020 for FIR as well
|
||||
// IGNORE_BACKEND_K2: JVM_IR
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
|
||||
@@ -31,4 +29,4 @@ fun box(): String {
|
||||
if (foo24 != "p2:24") return "FAIL2: foo24=$foo24"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user