diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index ee9ecf19f8e..88ff906110a 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -217,7 +217,7 @@ class Fir2IrConverter( } is FirField -> { if (declaration.isSynthetic) { - declarationStorage.createIrFieldAndDelegatedMembers(declaration, parent as IrClass) + declarationStorage.createIrFieldAndDelegatedMembers(declaration, containingClass!!, parent as IrClass) } else { throw AssertionError("Unexpected non-synthetic field: ${declaration::class}") } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 6673f718c97..f498a35e4e4 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -370,6 +370,10 @@ class Fir2IrDeclarationStorage( } } + internal fun cacheIrSimpleFunction(function: FirSimpleFunction, irFunction: IrSimpleFunction) { + functionCache[function] = irFunction + } + internal fun declareIrSimpleFunction( signature: IdSignature?, containerSource: DeserializedContainerSource?, @@ -737,12 +741,16 @@ class Fir2IrDeclarationStorage( fun getCachedIrProperty(property: FirProperty): IrProperty? = propertyCache[property] + internal fun cacheIrProperty(property: FirProperty, irProperty: IrProperty) { + propertyCache[property] = irProperty + } + fun getCachedIrField(field: FirField): IrField? = fieldCache[field] - fun createIrFieldAndDelegatedMembers(field: FirField, parent: IrClass): IrField { + fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass<*>, irClass: IrClass): IrField { val irField = createIrField(field, origin = IrDeclarationOrigin.DELEGATE) - irField.setAndModifyParent(parent) - delegatedMemberGenerator.generate(irField, parent) + irField.setAndModifyParent(irClass) + delegatedMemberGenerator.generate(irField, owner, irClass) return irField } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt index bd6226a3235..ca57593eb9d 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameterCopy import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl +import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol @@ -54,7 +55,7 @@ internal class DelegatedMemberGenerator( ) : Fir2IrComponents by components { // Generate delegated members for [subClass]. The synthetic field [irField] has the super interface type. - fun generate(irField: IrField, subClass: IrClass) { + fun generate(irField: IrField, firSubClass: FirClass<*>, subClass: IrClass) { val delegateClass = (irField.type as IrSimpleTypeImpl).classOrNull?.owner ?: return val subClasses = mutableMapOf(delegateClass to mutableListOf(subClass)) DFS.dfs( @@ -73,21 +74,50 @@ internal class DelegatedMemberGenerator( ) for ((superClass, mayOverride) in subClasses) { - val classId = superClass.classId ?: continue - if (classId == irBuiltIns.anyClass.owner.classId) continue + val superClassId = superClass.classId ?: continue + if (superClassId == irBuiltIns.anyClass.owner.classId) continue for (member in superClass.declarations) { val delegatable = member.isDelegatable() && !DFS.ifAny(mayOverride, { subClasses[it] ?: emptyList() }) { // Delegate to the most specific version of each member. it.declarations.any { !it.isFakeOverride && it.overrides(member) } } if (!delegatable) continue + val scope = firSubClass.unsubstitutedScope(session, scopeSession) if (member is IrSimpleFunction) { - val firFunction = declarationStorage.findOverriddenFirFunction(member, classId) ?: return - val function = generateDelegatedFunction(subClass, irField, member, firFunction) - subClass.addMember(function) + val firSuperFunction = declarationStorage.findOverriddenFirFunction(member, superClassId) ?: return + var firSubFunction: FirSimpleFunction? = null + scope.processFunctionsByName(member.name) { + if (it.callableId.classId == firSubClass.classId) { + var overriddenFunctionSymbol = it.overriddenSymbol + while (overriddenFunctionSymbol != null) { + if (overriddenFunctionSymbol.fir == firSuperFunction) { + firSubFunction = it.fir as FirSimpleFunction + break + } + overriddenFunctionSymbol = overriddenFunctionSymbol.overriddenSymbol + } + } + } + val irSubFunction = generateDelegatedFunction(subClass, irField, member, firSuperFunction) + firSubFunction?.let { declarationStorage.cacheIrSimpleFunction(it, irSubFunction) } + subClass.addMember(irSubFunction) } else if (member is IrProperty) { - val firProperty = declarationStorage.findOverriddenFirProperty(member, classId) ?: return - generateDelegatedProperty(subClass, irField, member, firProperty) + val firSuperProperty = declarationStorage.findOverriddenFirProperty(member, superClassId) ?: return + var firSubProperty: FirProperty? = null + scope.processPropertiesByName(member.name) { + if (it.callableId.classId == firSubClass.classId) { + var overriddenPropertySymbol = it.overriddenSymbol + while (overriddenPropertySymbol != null) { + if (overriddenPropertySymbol.fir == firSuperProperty) { + firSubProperty = it.fir as FirProperty + break + } + overriddenPropertySymbol = overriddenPropertySymbol.overriddenSymbol + } + } + } + val irSubProperty = generateDelegatedProperty(subClass, irField, member, firSuperProperty) + firSubProperty?.let { declarationStorage.cacheIrProperty(it, irSubProperty) } } } } @@ -305,12 +335,12 @@ internal class DelegatedMemberGenerator( irField: IrField, superProperty: IrProperty, firSuperProperty: FirProperty - ) { + ): IrProperty { val startOffset = irField.startOffset val endOffset = irField.endOffset val descriptor = WrappedPropertyDescriptor() val modality = if (superProperty.modality == Modality.ABSTRACT) Modality.OPEN else superProperty.modality - symbolTable.declareProperty( + return symbolTable.declareProperty( startOffset, endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, descriptor, superProperty.isDelegated ) { symbol -> diff --git a/compiler/testData/codegen/box/bridges/substitutionInSuperClass/delegation.kt b/compiler/testData/codegen/box/bridges/substitutionInSuperClass/delegation.kt index 9b7dc734c54..3d80f6523ea 100644 --- a/compiler/testData/codegen/box/bridges/substitutionInSuperClass/delegation.kt +++ b/compiler/testData/codegen/box/bridges/substitutionInSuperClass/delegation.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR interface A { fun id(t: T): T } diff --git a/compiler/testData/codegen/box/classes/typedDelegation.kt b/compiler/testData/codegen/box/classes/typedDelegation.kt index 8924f4d68e9..e0b1241a6aa 100644 --- a/compiler/testData/codegen/box/classes/typedDelegation.kt +++ b/compiler/testData/codegen/box/classes/typedDelegation.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR interface A { var zzzValue : T fun zzz() : T diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt index 44b0a32ffef..25692ded1b3 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // WITH_RUNTIME // KJS_WITH_FULL_RUNTIME diff --git a/compiler/testData/codegen/box/inlineClasses/interfaceDelegation/kt38337.kt b/compiler/testData/codegen/box/inlineClasses/interfaceDelegation/kt38337.kt index 180c5a8b527..4ef76daf60f 100644 --- a/compiler/testData/codegen/box/inlineClasses/interfaceDelegation/kt38337.kt +++ b/compiler/testData/codegen/box/inlineClasses/interfaceDelegation/kt38337.kt @@ -1,6 +1,5 @@ // KJS_WITH_FULL_RUNTIME // WITH_RUNTIME -// IGNORE_BACKEND_FIR: JVM_IR inline class Wrapper(val id: Int) diff --git a/compiler/testData/codegen/box/jdk/streamBackwardCompatibility.kt b/compiler/testData/codegen/box/jdk/streamBackwardCompatibility.kt index a5acd41f94c..5156b75eded 100644 --- a/compiler/testData/codegen/box/jdk/streamBackwardCompatibility.kt +++ b/compiler/testData/codegen/box/jdk/streamBackwardCompatibility.kt @@ -1,5 +1,4 @@ // !LANGUAGE: -AdditionalBuiltInsMembers -// IGNORE_BACKEND_FIR: JVM_IR // SKIP_JDK6 // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/properties/kt4373.kt b/compiler/testData/codegen/box/properties/kt4373.kt index bb3c37f7b5e..41b781f2cfc 100644 --- a/compiler/testData/codegen/box/properties/kt4373.kt +++ b/compiler/testData/codegen/box/properties/kt4373.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR interface Tr { val prop: T }