[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 symbols = createPropertySymbols(signature, property, fakeOverrideOwnerLookupTag)
|
||||||
val irParent = findIrParent(property, fakeOverrideOwnerLookupTag)
|
val irParent = findIrParent(property, fakeOverrideOwnerLookupTag)
|
||||||
if (irParent?.isExternalParent() == true) {
|
if (irParent?.isExternalParent() == true) {
|
||||||
|
val firForLazyProperty = calculateFirForLazyDeclaration(
|
||||||
|
property, fakeOverrideOwnerLookupTag, irParent,
|
||||||
|
fakeOverrideGenerator::createFirPropertyFakeOverrideIfNeeded
|
||||||
|
)
|
||||||
|
|
||||||
callablesGenerator.createIrProperty(
|
callablesGenerator.createIrProperty(
|
||||||
property,
|
firForLazyProperty,
|
||||||
irParent,
|
irParent,
|
||||||
symbols,
|
symbols,
|
||||||
predefinedOrigin = property.computeExternalOrigin(),
|
predefinedOrigin = firForLazyProperty.computeExternalOrigin(),
|
||||||
allowLazyDeclarationsCreation = true
|
allowLazyDeclarationsCreation = true
|
||||||
).also {
|
).also {
|
||||||
check(it is Fir2IrLazyProperty)
|
check(it is Fir2IrLazyProperty)
|
||||||
@@ -991,13 +996,17 @@ class Fir2IrDeclarationStorage(
|
|||||||
if (function is FirSimpleFunction && !isLocal) {
|
if (function is FirSimpleFunction && !isLocal) {
|
||||||
val irParent = findIrParent(function, fakeOverrideOwnerLookupTag)
|
val irParent = findIrParent(function, fakeOverrideOwnerLookupTag)
|
||||||
if (irParent?.isExternalParent() == true) {
|
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
|
// 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
|
// And all we want here is to bind symbol for lazy declaration
|
||||||
callablesGenerator.createIrFunction(
|
callablesGenerator.createIrFunction(
|
||||||
function,
|
firForLazyFunction,
|
||||||
irParent,
|
irParent,
|
||||||
symbol,
|
symbol,
|
||||||
predefinedOrigin = function.computeExternalOrigin(),
|
predefinedOrigin = firForLazyFunction.computeExternalOrigin(),
|
||||||
isLocal = false,
|
isLocal = false,
|
||||||
fakeOverrideOwnerLookupTag,
|
fakeOverrideOwnerLookupTag,
|
||||||
allowLazyDeclarationsCreation = true
|
allowLazyDeclarationsCreation = true
|
||||||
@@ -1131,6 +1140,16 @@ class Fir2IrDeclarationStorage(
|
|||||||
return null
|
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?) {
|
private fun generateLazyFakeOverrides(name: Name, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?) {
|
||||||
val firClassSymbol = fakeOverrideOwnerLookupTag?.toSymbol(session) as? FirClassSymbol
|
val firClassSymbol = fakeOverrideOwnerLookupTag?.toSymbol(session) as? FirClassSymbol
|
||||||
if (firClassSymbol != null) {
|
if (firClassSymbol != null) {
|
||||||
|
|||||||
@@ -118,7 +118,11 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
|
|||||||
scope.processFunctionsByName(lastName) { functionSymbol ->
|
scope.processFunctionsByName(lastName) { functionSymbol ->
|
||||||
val dispatchReceiverClassId = (functionSymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
|
val dispatchReceiverClassId = (functionSymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
|
||||||
val function = if (dispatchReceiverClassId != null && dispatchReceiverClassId != 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
|
} else functionSymbol.fir
|
||||||
functions.add(function)
|
functions.add(function)
|
||||||
}
|
}
|
||||||
@@ -135,7 +139,11 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
|
|||||||
propertySymbol as FirPropertySymbol
|
propertySymbol as FirPropertySymbol
|
||||||
val dispatchReceiverClassId = (propertySymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
|
val dispatchReceiverClassId = (propertySymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
|
||||||
val property = if (dispatchReceiverClassId != null && dispatchReceiverClassId != 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
|
} else propertySymbol.fir
|
||||||
properties.add(property)
|
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.declarations.utils.isStatic
|
||||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
import org.jetbrains.kotlin.fir.resolve.isRealOwnerOf
|
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.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.scopes.*
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
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.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class FakeOverrideGenerator(
|
class FakeOverrideGenerator(
|
||||||
@@ -314,80 +316,71 @@ class FakeOverrideGenerator(
|
|||||||
result?.add(owner)
|
result?.add(owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <D : FirCallableDeclaration, reified S : FirCallableSymbol<D>> createFirFakeOverride(
|
private inline fun <D : FirCallableDeclaration, reified S : FirCallableSymbol<D>> createFirFakeOverrideIfNeeded(
|
||||||
klass: FirClass,
|
dispatchReceiverLookupTag: ConeClassLikeLookupTag,
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
originalSymbol: S,
|
originalSymbol: S,
|
||||||
createFakeOverrideSymbol: (firDeclaration: D, baseSymbol: S) -> S,
|
createFakeOverrideSymbol: (firDeclaration: D) -> S,
|
||||||
computeDirectOverridden: FirTypeScope.(S) -> List<S>,
|
): D? {
|
||||||
scope: FirTypeScope,
|
|
||||||
): Pair<D, List<S>>? {
|
|
||||||
val classLookupTag = klass.symbol.toLookupTag()
|
|
||||||
val originalDeclaration = originalSymbol.fir
|
val originalDeclaration = originalSymbol.fir
|
||||||
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
|
|
||||||
return when {
|
return when {
|
||||||
originalSymbol.shouldHaveComputedBaseSymbolsForClass(classLookupTag) -> {
|
originalSymbol.containingClassLookupTag() == dispatchReceiverLookupTag -> null
|
||||||
// Substitution or intersection case
|
|
||||||
// We have already a FIR declaration for such fake override
|
|
||||||
originalDeclaration to computeBaseSymbols(
|
|
||||||
originalSymbol,
|
|
||||||
computeDirectOverridden,
|
|
||||||
scope, classLookupTag
|
|
||||||
)
|
|
||||||
}
|
|
||||||
originalDeclaration.allowsToHaveFakeOverride -> {
|
originalDeclaration.allowsToHaveFakeOverride -> {
|
||||||
// Trivial fake override case
|
// 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
|
// 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)
|
declarationStorage.saveFakeOverrideInClass(irClass, originalDeclaration, fakeOverrideSymbol.fir)
|
||||||
classifierStorage.preCacheTypeParameters(originalDeclaration, irClass.symbol)
|
fakeOverrideSymbol.fir
|
||||||
fakeOverrideSymbol.fir to listOf(originalSymbol)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun createFirFunctionFakeOverride(
|
internal fun createFirFunctionFakeOverrideIfNeeded(
|
||||||
klass: FirClass,
|
originalFunction: FirSimpleFunction,
|
||||||
|
dispatchReceiverLookupTag: ConeClassLikeLookupTag,
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
originalSymbol: FirNamedFunctionSymbol,
|
): FirSimpleFunction? {
|
||||||
scope: FirTypeScope
|
val originalSymbol = originalFunction.symbol
|
||||||
) = createFirFakeOverride(
|
return createFirFakeOverrideIfNeeded(
|
||||||
klass, irClass, originalSymbol,
|
dispatchReceiverLookupTag, irClass, originalSymbol
|
||||||
createFakeOverrideSymbol = { firFunction, callableSymbol ->
|
) { firFunction ->
|
||||||
|
val containingClass = dispatchReceiverLookupTag.toFirRegularClass(session)!!
|
||||||
FirFakeOverrideGenerator.createSubstitutionOverrideFunction(
|
FirFakeOverrideGenerator.createSubstitutionOverrideFunction(
|
||||||
session, callableSymbol, firFunction,
|
session,
|
||||||
derivedClassLookupTag = klass.symbol.toLookupTag(),
|
FirNamedFunctionSymbol(CallableId(containingClass.symbol.classId, originalSymbol.callableId.callableName)),
|
||||||
newDispatchReceiverType = klass.defaultType(),
|
firFunction,
|
||||||
|
derivedClassLookupTag = dispatchReceiverLookupTag,
|
||||||
|
newDispatchReceiverType = containingClass.defaultType(),
|
||||||
origin = FirDeclarationOrigin.SubstitutionOverride.DeclarationSite,
|
origin = FirDeclarationOrigin.SubstitutionOverride.DeclarationSite,
|
||||||
isExpect = (klass as? FirRegularClass)?.isExpect == true || firFunction.isExpect
|
isExpect = containingClass.isExpect || firFunction.isExpect
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
computeDirectOverridden = FirTypeScope::getDirectOverriddenFunctions,
|
}
|
||||||
scope
|
|
||||||
)
|
|
||||||
|
|
||||||
internal fun createFirPropertyFakeOverride(
|
internal fun createFirPropertyFakeOverrideIfNeeded(
|
||||||
klass: FirClass,
|
originalProperty: FirProperty,
|
||||||
|
dispatchReceiverLookupTag: ConeClassLikeLookupTag,
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
originalSymbol: FirPropertySymbol,
|
): FirProperty? {
|
||||||
scope: FirTypeScope
|
val originalSymbol = originalProperty.symbol
|
||||||
) = createFirFakeOverride(
|
return createFirFakeOverrideIfNeeded(
|
||||||
klass, irClass, originalSymbol,
|
dispatchReceiverLookupTag, irClass, originalSymbol
|
||||||
createFakeOverrideSymbol = { firProperty, callableSymbol ->
|
) { firProperty ->
|
||||||
|
val containingClass = dispatchReceiverLookupTag.toFirRegularClass(session)!!
|
||||||
FirFakeOverrideGenerator.createSubstitutionOverrideProperty(
|
FirFakeOverrideGenerator.createSubstitutionOverrideProperty(
|
||||||
session, callableSymbol, firProperty,
|
session,
|
||||||
derivedClassLookupTag = klass.symbol.toLookupTag(),
|
FirPropertySymbol(CallableId(containingClass.symbol.classId, originalSymbol.callableId.callableName)),
|
||||||
newDispatchReceiverType = klass.defaultType(),
|
firProperty,
|
||||||
|
derivedClassLookupTag = dispatchReceiverLookupTag,
|
||||||
|
newDispatchReceiverType = containingClass.defaultType(),
|
||||||
origin = FirDeclarationOrigin.SubstitutionOverride.DeclarationSite,
|
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(
|
private inline fun <reified S : FirCallableSymbol<*>> computeBaseSymbols(
|
||||||
symbol: S,
|
symbol: S,
|
||||||
|
|||||||
+4
-3
@@ -1,7 +1,8 @@
|
|||||||
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
|
// IGNORE_BACKEND_K2: JS_IR
|
||||||
// KT-59609
|
|
||||||
// IGNORE_BACKEND: NATIVE
|
// 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
|
// MODULE: lib
|
||||||
// FILE: a.kt
|
// FILE: a.kt
|
||||||
package a
|
package a
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
|
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION
|
||||||
// FIR status: validation failed. TODO decide if we want to fix KT-42020 for FIR as well
|
// Reason: KT-42020
|
||||||
|
|
||||||
open class Base<T> {
|
open class Base<T> {
|
||||||
fun foo(x: T) = "x:$x"
|
fun foo(x: T) = "x:$x"
|
||||||
@@ -26,4 +26,4 @@ fun box(): String {
|
|||||||
throw Exception("test4: $test4")
|
throw Exception("test4: $test4")
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -7,8 +7,6 @@
|
|||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_BACKEND_K2: NATIVE, JS_IR
|
// 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
|
// MODULE: lib
|
||||||
// FILE: lib.kt
|
// FILE: lib.kt
|
||||||
|
|
||||||
@@ -31,4 +29,4 @@ fun box(): String {
|
|||||||
if (foo24 != "p2:24") return "FAIL2: foo24=$foo24"
|
if (foo24 != "p2:24") return "FAIL2: foo24=$foo24"
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user