[IrFakeOverrideBuilder] Support fake overrides for java static methods
^KT-64150
This commit is contained in:
committed by
Space Team
parent
8f046d36e0
commit
15094eb03a
+1
-1
@@ -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 {}
|
||||||
|
|||||||
Reference in New Issue
Block a user