IR: simplify IrFakeOverrideBuilder.isMoreSpecific

Using the logic from `OverridingUtil.isMoreSpecific` as a reference.
This commit is contained in:
Alexander Udalov
2024-03-05 09:50:44 +01:00
committed by Space Team
parent 5c64832c0f
commit 9a7d7483a3
@@ -374,65 +374,26 @@ class IrFakeOverrideBuilder(
return AbstractTypeChecker.isSubtypeOf(typeCheckerState, a.returnType, b.returnType) return AbstractTypeChecker.isSubtypeOf(typeCheckerState, a.returnType, b.returnType)
} }
private fun isMoreSpecific( private fun isMoreSpecific(a: IrOverridableMember, b: IrOverridableMember): Boolean {
a: IrOverridableMember, if (!isVisibilityMoreSpecific(a, b)) return false
b: IrOverridableMember
): Boolean { if (a is IrProperty) {
return a >= b check(b is IrProperty) { "b is not a property: $b" }
if (!isAccessorMoreSpecific(a.setter, b.setter)) return false
if (!a.isVar && b.isVar) return false
}
return isReturnTypeIsSubtypeOfOtherReturnType(a, b)
} }
// Based on compareTo from FirOverrideService.kt private fun isVisibilityMoreSpecific(a: IrOverridableMember, b: IrOverridableMember): Boolean {
private operator fun IrOverridableMember.compareTo(other: IrOverridableMember): Int { val result = DescriptorVisibilities.compare(a.visibility, b.visibility)
fun merge(preferA: Boolean, preferB: Boolean, previous: Int): Int = when { return result == null || result >= 0
preferA == preferB -> previous
preferA && previous >= 0 -> 1
preferB && previous <= 0 -> -1
else -> 0
}
val aIr = this@compareTo
val bIr = other
val byVisibility = DescriptorVisibilities.compare(aIr.visibility, bIr.visibility) ?: 0
val aReturnType = aIr.returnType
val bReturnType = bIr.returnType
val aSubtypesB = isReturnTypeIsSubtypeOfOtherReturnType(aIr, bIr)
val bSubtypesA = isReturnTypeIsSubtypeOfOtherReturnType(bIr, aIr)
val byVisibilityAndType = when {
// Could be that one of them is flexible, in which case the types are not equal but still subtypes of one another;
// make the inflexible one more specific.
aSubtypesB && bSubtypesA -> merge(!aReturnType.isFlexible(), !bReturnType.isFlexible(), byVisibility)
aSubtypesB && byVisibility >= 0 -> 1
bSubtypesA && byVisibility <= 0 -> -1
else -> 0
}
return when (aIr) {
is IrSimpleFunction -> byVisibilityAndType
is IrProperty -> {
require(bIr is IrProperty)
val settersComparison = if (aIr.isVar && bIr.isVar) {
val aSetter = aIr.setter
val bSetter = bIr.setter
when {
aSetter != null && bSetter != null -> aSetter.compareTo(bSetter)
else -> 0
}
} else {
0
}
val bySetters = merge(
preferA = settersComparison >= 0,
preferB = settersComparison <= 0,
byVisibilityAndType
)
merge(aIr.isVar, bIr.isVar, bySetters)
}
else -> error("Unexpected type: $aIr")
}
} }
private fun isAccessorMoreSpecific(a: IrSimpleFunction?, b: IrSimpleFunction?): Boolean =
a == null || b == null || isVisibilityMoreSpecific(a, b)
private fun IrType.isFlexible(): Boolean { private fun IrType.isFlexible(): Boolean {
return with(typeSystem) { isFlexible() } return with(typeSystem) { isFlexible() }
} }