[IrFakeOverrideBuilder] Support fake overrides for java static methods

^KT-64150
This commit is contained in:
Pavel Kunyavskiy
2024-01-11 18:33:47 +01:00
committed by Space Team
parent 8f046d36e0
commit 15094eb03a
4 changed files with 12 additions and 21 deletions
@@ -39,7 +39,7 @@ abstract class FakeOverrideBuilderStrategy(
* if no fake override should be created for this member * if no fake override should be created for this member
*/ */
fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember? { fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember? {
return if (isVisibleForOverrideInClass(member, clazz)) return if (member.isOverridableMemberOrAccessor() && isVisibleForOverrideInClass(member, clazz))
buildFakeOverrideMember(superType, member, clazz, unimplementedOverridesStrategy) buildFakeOverrideMember(superType, member, clazz, unimplementedOverridesStrategy)
else else
null null
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.collectAndFilterRealOverrides import org.jetbrains.kotlin.ir.util.collectAndFilterRealOverrides
import org.jetbrains.kotlin.ir.util.fileOrNull import org.jetbrains.kotlin.ir.util.fileOrNull
import org.jetbrains.kotlin.ir.util.isFromJava
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -68,16 +69,15 @@ class IrFakeOverrideBuilder(
val allFromSuper = clazz.superTypes.flatMap { superType -> val allFromSuper = clazz.superTypes.flatMap { superType ->
val superClass = superType.getClass() ?: error("Unexpected super type: $superType") val superClass = superType.getClass() ?: error("Unexpected super type: $superType")
superClass.declarations superClass.declarations
.filter { it.isOverridableMemberOrAccessor() } .filterIsInstance<IrOverridableMember>()
.mapNotNull { .mapNotNull {
val overriddenMember = it as IrOverridableMember val fakeOverride = strategy.fakeOverrideMember(superType, it, clazz) ?: return@mapNotNull null
val fakeOverride = strategy.fakeOverrideMember(superType, overriddenMember, clazz) ?: return@mapNotNull null FakeOverride(fakeOverride, it)
FakeOverride(fakeOverride, overriddenMember)
} }
} }
val allFromSuperByName = allFromSuper.groupBy { it.override.name } val allFromSuperByName = allFromSuper.groupBy { it.override.name }
val allFromCurrentByName = clazz.declarations.filterIsInstanceAnd<IrOverridableMember> { !it.isStaticMember }.groupBy { it.name } val allFromCurrentByName = clazz.declarations.filterIsInstance<IrOverridableMember>().groupBy { it.name }
allFromSuperByName.forEach { (name, superMembers) -> allFromSuperByName.forEach { (name, superMembers) ->
generateOverridesInFunctionGroup( generateOverridesInFunctionGroup(
@@ -110,7 +110,7 @@ class IrFakeOverrideBuilder(
val superClass = superType.getClass() ?: error("Unexpected super type: $superType") val superClass = superType.getClass() ?: error("Unexpected super type: $superType")
superClass.declarations superClass.declarations
.filterIsInstanceAnd<IrOverridableMember> { .filterIsInstanceAnd<IrOverridableMember> {
it !in overriddenMembers && it.symbol !in ignoredParentSymbols && !it.isStaticMember it !in overriddenMembers && it.symbol !in ignoredParentSymbols
} }
.mapNotNull { overriddenMember -> .mapNotNull { overriddenMember ->
val fakeOverride = strategy.fakeOverrideMember(superType, overriddenMember, clazz) ?: return@mapNotNull null val fakeOverride = strategy.fakeOverrideMember(superType, overriddenMember, clazz) ?: return@mapNotNull null
@@ -126,16 +126,6 @@ class IrFakeOverrideBuilder(
return fakeOverrides return fakeOverrides
} }
private val IrOverridableMember.isStaticMember: Boolean
get() = when (this) {
is IrFunction ->
dispatchReceiverParameter == null
is IrProperty ->
backingField?.isStatic == true ||
getter?.let { it.dispatchReceiverParameter == null } == true
else -> error("Unknown overridable member: ${render()}")
}
private fun generateOverridesInFunctionGroup( private fun generateOverridesInFunctionGroup(
membersFromSupertypes: List<FakeOverride>, membersFromSupertypes: List<FakeOverride>,
membersFromCurrent: List<IrOverridableMember>, membersFromCurrent: List<IrOverridableMember>,
@@ -177,7 +167,7 @@ class IrFakeOverrideBuilder(
// because of binary incompatible changes, it's possible to have private member colliding with fake override // because of binary incompatible changes, it's possible to have private member colliding with fake override
// In that case we shouldn't generate fake override, but also shouldn't mark them as overridden // In that case we shouldn't generate fake override, but also shouldn't mark them as overridden
if (!DescriptorVisibilities.isPrivate(fromCurrent.visibility)) { if (fromCurrent.isOverridableMemberOrAccessor()) {
fromCurrent.overriddenSymbols = overridden.memoryOptimizedMap { it.original.symbol } fromCurrent.overriddenSymbols = overridden.memoryOptimizedMap { it.original.symbol }
} }
@@ -502,10 +492,10 @@ private val IrOverridableMember.returnType: IrType
} }
fun IrSimpleFunction.isOverridableFunction(): Boolean = fun IrSimpleFunction.isOverridableFunction(): Boolean =
!DescriptorVisibilities.isPrivate(visibility) && hasDispatchReceiver !DescriptorVisibilities.isPrivate(visibility) && (hasDispatchReceiver || isFromJava())
fun IrProperty.isOverridableProperty(): Boolean = fun IrProperty.isOverridableProperty(): Boolean =
!DescriptorVisibilities.isPrivate(visibility) && (getter.hasDispatchReceiver || setter.hasDispatchReceiver) !DescriptorVisibilities.isPrivate(visibility) && (getter.hasDispatchReceiver || setter.hasDispatchReceiver || isFromJava())
fun IrDeclaration.isOverridableMemberOrAccessor(): Boolean = when (this) { fun IrDeclaration.isOverridableMemberOrAccessor(): Boolean = when (this) {
is IrSimpleFunction -> isOverridableFunction() is IrSimpleFunction -> isOverridableFunction()
@@ -65,6 +65,7 @@ class IrOverrideChecker(
is IrSimpleFunction -> when { is IrSimpleFunction -> when {
subMember !is IrSimpleFunction -> return incompatible("Member kind mismatch") subMember !is IrSimpleFunction -> return incompatible("Member kind mismatch")
superMember.hasExtensionReceiver != subMember.hasExtensionReceiver -> return incompatible("Receiver presence mismatch") superMember.hasExtensionReceiver != subMember.hasExtensionReceiver -> return incompatible("Receiver presence mismatch")
superMember.hasDispatchReceiver != subMember.hasDispatchReceiver -> return incompatible("Incompatible staticness")
superMember.isSuspend != subMember.isSuspend -> return incompatible("Incompatible suspendability") superMember.isSuspend != subMember.isSuspend -> return incompatible("Incompatible suspendability")
checkIsInlineFlag && superMember.isInline -> return incompatible("Inline function can't be overridden") checkIsInlineFlag && superMember.isInline -> return incompatible("Inline function can't be overridden")
@@ -78,6 +79,7 @@ class IrOverrideChecker(
is IrProperty -> when { is IrProperty -> when {
subMember !is IrProperty -> return incompatible("Member kind mismatch") subMember !is IrProperty -> return incompatible("Member kind mismatch")
superMember.getter.hasExtensionReceiver != subMember.getter.hasExtensionReceiver -> return incompatible("Receiver presence mismatch") superMember.getter.hasExtensionReceiver != subMember.getter.hasExtensionReceiver -> return incompatible("Receiver presence mismatch")
superMember.getter.hasDispatchReceiver != subMember.getter.hasDispatchReceiver -> return incompatible("Incompatible staticness")
checkIsInlineFlag && superMember.isInline -> return incompatible("Inline property can't be overridden") checkIsInlineFlag && superMember.isInline -> return incompatible("Inline property can't be overridden")
else -> { else -> {
@@ -1,5 +1,4 @@
// TARGET_BACKEND: JVM_IR // TARGET_BACKEND: JVM_IR
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-64150
// FILE: AbstractBlackBoxCodegenTest.java // FILE: AbstractBlackBoxCodegenTest.java
public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {} public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {}