From 15094eb03a6e89d014228a8dce372fffcc5d3ced Mon Sep 17 00:00:00 2001 From: Pavel Kunyavskiy Date: Thu, 11 Jan 2024 18:33:47 +0100 Subject: [PATCH] [IrFakeOverrideBuilder] Support fake overrides for java static methods ^KT-64150 --- .../overrides/FakeOverrideBuilderStrategy.kt | 2 +- .../ir/overrides/IrFakeOverrideBuilder.kt | 28 ++++++------------- .../kotlin/ir/overrides/IrOverrideChecker.kt | 2 ++ .../box/fir/assertEqualsFakeOverride.kt | 1 - 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/FakeOverrideBuilderStrategy.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/FakeOverrideBuilderStrategy.kt index 0efd8bac12f..e4d52616c82 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/FakeOverrideBuilderStrategy.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/FakeOverrideBuilderStrategy.kt @@ -39,7 +39,7 @@ abstract class FakeOverrideBuilderStrategy( * if no fake override should be created for this member */ 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) else null diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrFakeOverrideBuilder.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrFakeOverrideBuilder.kt index 6e255d0aac0..b4bc2cdf110 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrFakeOverrideBuilder.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrFakeOverrideBuilder.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.collectAndFilterRealOverrides 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.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -68,16 +69,15 @@ class IrFakeOverrideBuilder( val allFromSuper = clazz.superTypes.flatMap { superType -> val superClass = superType.getClass() ?: error("Unexpected super type: $superType") superClass.declarations - .filter { it.isOverridableMemberOrAccessor() } + .filterIsInstance() .mapNotNull { - val overriddenMember = it as IrOverridableMember - val fakeOverride = strategy.fakeOverrideMember(superType, overriddenMember, clazz) ?: return@mapNotNull null - FakeOverride(fakeOverride, overriddenMember) + val fakeOverride = strategy.fakeOverrideMember(superType, it, clazz) ?: return@mapNotNull null + FakeOverride(fakeOverride, it) } } val allFromSuperByName = allFromSuper.groupBy { it.override.name } - val allFromCurrentByName = clazz.declarations.filterIsInstanceAnd { !it.isStaticMember }.groupBy { it.name } + val allFromCurrentByName = clazz.declarations.filterIsInstance().groupBy { it.name } allFromSuperByName.forEach { (name, superMembers) -> generateOverridesInFunctionGroup( @@ -110,7 +110,7 @@ class IrFakeOverrideBuilder( val superClass = superType.getClass() ?: error("Unexpected super type: $superType") superClass.declarations .filterIsInstanceAnd { - it !in overriddenMembers && it.symbol !in ignoredParentSymbols && !it.isStaticMember + it !in overriddenMembers && it.symbol !in ignoredParentSymbols } .mapNotNull { overriddenMember -> val fakeOverride = strategy.fakeOverrideMember(superType, overriddenMember, clazz) ?: return@mapNotNull null @@ -126,16 +126,6 @@ class IrFakeOverrideBuilder( 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( membersFromSupertypes: List, membersFromCurrent: List, @@ -177,7 +167,7 @@ class IrFakeOverrideBuilder( // 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 - if (!DescriptorVisibilities.isPrivate(fromCurrent.visibility)) { + if (fromCurrent.isOverridableMemberOrAccessor()) { fromCurrent.overriddenSymbols = overridden.memoryOptimizedMap { it.original.symbol } } @@ -502,10 +492,10 @@ private val IrOverridableMember.returnType: IrType } fun IrSimpleFunction.isOverridableFunction(): Boolean = - !DescriptorVisibilities.isPrivate(visibility) && hasDispatchReceiver + !DescriptorVisibilities.isPrivate(visibility) && (hasDispatchReceiver || isFromJava()) 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) { is IrSimpleFunction -> isOverridableFunction() diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverrideChecker.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverrideChecker.kt index 55e04e40585..16e032155a3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverrideChecker.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverrideChecker.kt @@ -65,6 +65,7 @@ class IrOverrideChecker( is IrSimpleFunction -> when { subMember !is IrSimpleFunction -> return incompatible("Member kind 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") checkIsInlineFlag && superMember.isInline -> return incompatible("Inline function can't be overridden") @@ -78,6 +79,7 @@ class IrOverrideChecker( is IrProperty -> when { subMember !is IrProperty -> return incompatible("Member kind 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") else -> { diff --git a/compiler/testData/codegen/box/fir/assertEqualsFakeOverride.kt b/compiler/testData/codegen/box/fir/assertEqualsFakeOverride.kt index 3733d852602..ebb6c4bcb5f 100644 --- a/compiler/testData/codegen/box/fir/assertEqualsFakeOverride.kt +++ b/compiler/testData/codegen/box/fir/assertEqualsFakeOverride.kt @@ -1,5 +1,4 @@ // TARGET_BACKEND: JVM_IR -// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-64150 // FILE: AbstractBlackBoxCodegenTest.java public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {}