IR: fix "most specific" check in IrFakeOverrideBuilder

There were several problems with it:

1) `isMoreSpecific` should return true if a == b. Otherwise
   `isMoreSpecificThenAllOf` would never return true because it's always
   invoked with a collection that contains the candidate. K1 behaves
   similarly, `OverridingUtil.isMoreSpecific` returns true if a == b.
   So in fact, "more" should be understood as "not less" here.
2) `transitivelyMostSpecificMember` in `selectMostSpecificMember` was
   always equal to the first element, so `isMoreSpecific` was invoked
   with incorrect arguments.
3) At the end of `selectMostSpecificMember`, we selected the first
   candidate with the non-flexible return type, however only dynamic
   type was considered. We need to check `isFlexible` via type system
   instead.

 #KT-66120 Fixed
This commit is contained in:
Alexander Udalov
2024-03-01 14:13:04 +01:00
committed by Space Team
parent a08df1821f
commit 77b3f415a5
17 changed files with 32 additions and 2761 deletions
@@ -378,7 +378,7 @@ class IrFakeOverrideBuilder(
a: IrOverridableMember,
b: IrOverridableMember
): Boolean {
return a > b
return a >= b
}
// Based on compareTo from FirOverrideService.kt
@@ -458,20 +458,12 @@ class IrFakeOverrideBuilder(
}
val candidates = mutableListOf<FakeOverride>()
var transitivelyMostSpecific = overridables.first()
val transitivelyMostSpecificMember = transitivelyMostSpecific
for (overridable in overridables) {
if (isMoreSpecificThenAllOf(overridable, overridables)
) {
if (isMoreSpecificThenAllOf(overridable, overridables)) {
candidates.add(overridable)
}
if (isMoreSpecific(
overridable.override,
transitivelyMostSpecificMember.override
)
&& !isMoreSpecific(
transitivelyMostSpecificMember.override,
overridable.override
)
if (isMoreSpecific(overridable.override, transitivelyMostSpecific.override)
&& !isMoreSpecific(transitivelyMostSpecific.override, overridable.override)
) {
transitivelyMostSpecific = overridable
}
@@ -483,7 +475,7 @@ class IrFakeOverrideBuilder(
}
var firstNonFlexible: FakeOverride? = null
for (candidate in candidates) {
if (candidate.override.returnType !is IrDynamicType) {
if (!candidate.override.returnType.isFlexible()) {
firstNonFlexible = candidate
break
}