diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 6d05ba86911..a439309d96c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -339,6 +339,7 @@ private val jvmFilePhases = listOf( interfacePhase, inheritedDefaultMethodsOnClassesPhase, + replaceDefaultImplsOverriddenSymbolsPhase, interfaceSuperCallsPhase, interfaceDefaultCallsPhase, interfaceObjectCallsPhase, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt index ebfd3ae720a..85e169f3ac5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt @@ -34,10 +34,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal val inheritedDefaultMethodsOnClassesPhase = makeIrFilePhase( @@ -46,39 +43,17 @@ internal val inheritedDefaultMethodsOnClassesPhase = makeIrFilePhase( description = "Add bridge-implementations in classes that inherit default implementations from interfaces" ) -private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendContext) : IrElementVisitorVoid, ClassLoweringPass { - - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - +private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { - if (!irClass.isJvmInterface) - generateInterfaceMethods(irClass) - - super.visitClass(irClass) - } - - private fun generateInterfaceMethods(irClass: IrClass) { - irClass.declarations.transformInPlace { declaration -> - (declaration as? IrSimpleFunction)?.findInterfaceImplementation(context.state.jvmDefaultMode)?.let { implementation -> - generateDelegationToDefaultImpl(implementation, declaration) - } ?: declaration + if (!irClass.isJvmInterface) { + irClass.declarations.transformInPlace { declaration -> + (declaration as? IrSimpleFunction)?.findInterfaceImplementation(context.state.jvmDefaultMode)?.let { implementation -> + generateDelegationToDefaultImpl(implementation, declaration) + } ?: declaration + } } } - // Functions introduced by this lowering may be inherited lower in the hierarchy. - // Here we use the same logic as the delegation itself (`getTargetForRedirection`) to determine - // if the overriden symbol has been, or will be, replaced and patch it accordingly. - override fun visitSimpleFunction(declaration: IrSimpleFunction) { - declaration.overriddenSymbols = declaration.overriddenSymbols.map { symbol -> - if (symbol.owner.findInterfaceImplementation(context.state.jvmDefaultMode) != null) - context.cachedDeclarations.getDefaultImplsRedirection(symbol.owner).symbol - else symbol - } - super.visitSimpleFunction(declaration) - } - private fun generateDelegationToDefaultImpl( interfaceImplementation: IrSimpleFunction, classOverride: IrSimpleFunction @@ -110,6 +85,34 @@ private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendCo } } +internal val replaceDefaultImplsOverriddenSymbolsPhase = makeIrFilePhase( + ::ReplaceDefaultImplsOverriddenSymbols, + name = "ReplaceDefaultImplsOverriddenSymbols", + description = "Replace overridden symbols for methods inherited from interfaces to classes" +) + +private class ReplaceDefaultImplsOverriddenSymbols(private val context: JvmBackendContext) : FileLoweringPass, IrElementVisitorVoid { + override fun lower(irFile: IrFile) { + irFile.acceptVoid(this) + } + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + // Functions introduced by InheritedDefaultMethodsOnClassesLowering may be inherited lower in the hierarchy. + // Here we use the same logic as the delegation itself (`getTargetForRedirection`) to determine + // if the overridden symbol has been, or will be, replaced and patch it accordingly. + override fun visitSimpleFunction(declaration: IrSimpleFunction) { + declaration.overriddenSymbols = declaration.overriddenSymbols.map { symbol -> + if (symbol.owner.findInterfaceImplementation(context.state.jvmDefaultMode) != null) + context.cachedDeclarations.getDefaultImplsRedirection(symbol.owner).symbol + else symbol + } + super.visitSimpleFunction(declaration) + } +} + internal val interfaceSuperCallsPhase = makeIrFilePhase( lowering = ::InterfaceSuperCallsLowering, name = "InterfaceSuperCalls", @@ -228,10 +231,10 @@ private class InterfaceObjectCallsLowering(val context: JvmBackendContext) : IrE * override of any interface implementation or such method was already generated into the superclass or is a method from Any. */ private fun isDefaultImplsBridge(f: IrSimpleFunction) = - f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE || - f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY || - f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC || - f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC + f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE || + f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY || + f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC || + f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC internal fun IrSimpleFunction.findInterfaceImplementation(jvmDefaultMode: JvmDefaultMode): IrSimpleFunction? { if (!isFakeOverride) return null