[JVM IR] Refactor InterfaceDelegationPhase
Rename and refactor interface delegation phase. It didn't actually do what was said on the box. It should be more in line with the intentions of the phase now.
This commit is contained in:
committed by
Alexander Udalov
parent
a5ff88f897
commit
0abdd0cb7b
@@ -290,7 +290,7 @@ private val jvmFilePhases =
|
||||
defaultArgumentInjectorPhase then
|
||||
|
||||
interfacePhase then
|
||||
interfaceDelegationPhase then
|
||||
inheritedDefaultMethodsOnClassesPhase then
|
||||
interfaceSuperCallsPhase then
|
||||
interfaceDefaultCallsPhase then
|
||||
interfaceObjectCallsPhase then
|
||||
|
||||
+1
-1
@@ -170,7 +170,7 @@ private fun IrDeclarationWithVisibility.specialCaseVisibility(kind: OwnerKind?):
|
||||
// return ACC_PUBLIC
|
||||
// }
|
||||
if (this is IrClass && Visibilities.isPrivate(visibility) &&
|
||||
parent.safeAs<IrClass>()?.isInterface ?: false
|
||||
hasInterfaceParent()
|
||||
) { // TODO: non-intrinsic
|
||||
return Opcodes.ACC_PUBLIC
|
||||
}
|
||||
|
||||
+2
-5
@@ -39,10 +39,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isNullable
|
||||
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -487,7 +484,7 @@ private data class SignatureWithSource(val signature: Method, val source: IrSimp
|
||||
|
||||
|
||||
fun IrSimpleFunction.overriddenInClasses(): Sequence<IrSimpleFunction> =
|
||||
allOverridden().filter { !(it.parent.safeAs<IrClass>()?.isInterface ?: true) }
|
||||
allOverridden().filterNot(IrDeclaration::hasInterfaceParent)
|
||||
|
||||
fun IrSimpleFunction.isCollectionStub(): Boolean =
|
||||
origin == IrDeclarationOrigin.IR_BUILTINS_STUB
|
||||
|
||||
+24
-32
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
||||
@@ -30,27 +31,25 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
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.utils.addToStdlib.safeAs
|
||||
|
||||
internal val interfaceDelegationPhase = makeIrFilePhase(
|
||||
::InterfaceDelegationLowering,
|
||||
name = "InterfaceDelegation",
|
||||
description = "Delegate calls to interface members with default implementations to DefaultImpls"
|
||||
internal val inheritedDefaultMethodsOnClassesPhase = makeIrFilePhase(
|
||||
::InheritedDefaultMethodsOnClassesLowering,
|
||||
name = "InheritedDefaultMethodsOnClasses",
|
||||
description = "Add bridge-implementations in classes that inherit default implementations from interfaces"
|
||||
)
|
||||
|
||||
private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrElementVisitorVoid, FileLoweringPass {
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.acceptChildrenVoid(this)
|
||||
irFile.acceptVoid(OverriddenSymbolsReplacer())
|
||||
}
|
||||
private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendContext) : IrElementVisitorVoid, ClassLoweringPass {
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
override fun lower(declaration: IrClass) {
|
||||
super.visitClass(declaration)
|
||||
if (declaration.isJvmInterface) return
|
||||
|
||||
@@ -65,6 +64,18 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
|
||||
}
|
||||
}
|
||||
|
||||
// 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.replaceAll { symbol ->
|
||||
if (symbol.owner.getTargetForRedirection() != null)
|
||||
context.declarationFactory.getDefaultImplsRedirection(symbol.owner).symbol
|
||||
else symbol
|
||||
}
|
||||
super.visitSimpleFunction(declaration)
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.getTargetForRedirection(): IrSimpleFunction? {
|
||||
if (origin != IrDeclarationOrigin.FAKE_OVERRIDE) return null
|
||||
parent.let { if (it is IrClass && it.isJvmInterface) return null }
|
||||
@@ -111,27 +122,8 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
|
||||
|
||||
return irFunction
|
||||
}
|
||||
|
||||
private inner class OverriddenSymbolsReplacer : IrElementVisitorVoid {
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
||||
declaration.overriddenSymbols.replaceAll { symbol ->
|
||||
if (symbol.owner.getTargetForRedirection() != null)
|
||||
context.declarationFactory.getDefaultImplsRedirection(symbol.owner).symbol
|
||||
else symbol
|
||||
}
|
||||
super.visitSimpleFunction(declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.hasInterfaceParent() =
|
||||
(parent as? IrClass)?.isInterface == true
|
||||
|
||||
internal val interfaceSuperCallsPhase = makeIrFilePhase(
|
||||
lowering = ::InterfaceSuperCallsLowering,
|
||||
name = "InterfaceSuperCalls",
|
||||
@@ -174,7 +166,7 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
val callee = expression.symbol.owner
|
||||
|
||||
if (callee.parent.safeAs<IrClass>()?.isInterface != true ||
|
||||
if (!callee.hasInterfaceParent() ||
|
||||
callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
(callee.hasJvmDefault() && !context.state.jvmDefaultMode.isCompatibility)
|
||||
) {
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
/**
|
||||
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
|
||||
@@ -379,6 +380,10 @@ fun IrFunction.isFakeOverriddenFromAny(): Boolean {
|
||||
|
||||
fun IrCall.isSuperToAny() = superQualifierSymbol?.let { this.symbol.owner.isFakeOverriddenFromAny() } ?: false
|
||||
|
||||
|
||||
fun IrDeclaration.hasInterfaceParent() =
|
||||
parent.safeAs<IrClass>()?.isInterface == true
|
||||
|
||||
fun IrDeclaration.isEffectivelyExternal(): Boolean {
|
||||
|
||||
fun IrFunction.effectiveParentDeclaration(): IrDeclaration? =
|
||||
|
||||
Reference in New Issue
Block a user