[FIR] Fix tower priorities for invoke resolve
#KT-45316 Fixed
This commit is contained in:
+5
@@ -750,6 +750,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/syntheticPropertiesWrongImplicitReceiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("twoLocalLambdasWithSameName.kt")
|
||||
public void testTwoLocalLambdasWithSameName() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/twoLocalLambdasWithSameName.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeAliasWithNotNullBound.kt")
|
||||
public void testTypeAliasWithNotNullBound() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/typeAliasWithNotNullBound.kt");
|
||||
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
FILE: twoLocalLambdasWithSameName.kt
|
||||
public abstract interface R : R|kotlin/Any| {
|
||||
}
|
||||
public final fun takeInt(x: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun test(fn: R|R.() -> kotlin/String|): R|kotlin/Unit| {
|
||||
lval renderer: R|<anonymous>| = object : R|R| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun render(fn: R|R.() -> kotlin/Int|): R|kotlin/Unit| {
|
||||
lval result: R|kotlin/Int| = R|<local>/fn|.R|SubstitutionOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(this@R|/<anonymous>|)
|
||||
R|/takeInt|(R|<local>/result|)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// ISSUE: KT-45316
|
||||
interface R
|
||||
|
||||
fun takeInt(x: Int) {}
|
||||
|
||||
fun test(fn: R.() -> String) { // (1)
|
||||
val renderer = object : R {
|
||||
fun render(fn: R.() -> Int) { // (2)
|
||||
val result = fn()
|
||||
takeInt(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -869,6 +869,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/syntheticPropertiesWrongImplicitReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("twoLocalLambdasWithSameName.kt")
|
||||
public void testTwoLocalLambdasWithSameName() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/twoLocalLambdasWithSameName.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeAliasWithNotNullBound.kt")
|
||||
public void testTypeAliasWithNotNullBound() throws Exception {
|
||||
|
||||
+6
@@ -876,6 +876,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/syntheticPropertiesWrongImplicitReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("twoLocalLambdasWithSameName.kt")
|
||||
public void testTwoLocalLambdasWithSameName() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/twoLocalLambdasWithSameName.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeAliasWithNotNullBound.kt")
|
||||
public void testTypeAliasWithNotNullBound() throws Exception {
|
||||
|
||||
+5
-2
@@ -331,8 +331,11 @@ private class InvokeFunctionResolveTask(
|
||||
candidateFactory,
|
||||
) {
|
||||
|
||||
override fun interceptTowerGroup(towerGroup: TowerGroup): TowerGroup =
|
||||
maxOf(towerGroup.InvokeResolvePriority(InvokeResolvePriority.COMMON_INVOKE), receiverGroup)
|
||||
override fun interceptTowerGroup(towerGroup: TowerGroup): TowerGroup {
|
||||
val invokeGroup = towerGroup.InvokeResolvePriority(InvokeResolvePriority.COMMON_INVOKE)
|
||||
val max = maxOf(invokeGroup, receiverGroup)
|
||||
return max.InvokeReceiver(receiverGroup)
|
||||
}
|
||||
|
||||
suspend fun runResolverForInvoke(
|
||||
info: CallInfo,
|
||||
|
||||
+19
-3
@@ -70,7 +70,8 @@ class TowerGroup
|
||||
private constructor(
|
||||
private val code: Long,
|
||||
private val debugKinds: Array<TowerGroupKind>,
|
||||
private val invokeResolvePriority: InvokeResolvePriority = InvokeResolvePriority.NONE
|
||||
private val invokeResolvePriority: InvokeResolvePriority = InvokeResolvePriority.NONE,
|
||||
private val receiverGroup: TowerGroup? = null
|
||||
) : Comparable<TowerGroup> {
|
||||
companion object {
|
||||
|
||||
@@ -183,6 +184,8 @@ private constructor(
|
||||
|
||||
fun TopPrioritized(depth: Int) = kindOf(TowerGroupKind.TopPrioritized(depth))
|
||||
|
||||
fun InvokeReceiver(receiverGroup: TowerGroup) = TowerGroup(code, debugKinds, invokeResolvePriority, receiverGroup)
|
||||
|
||||
// Treating `a.foo()` common calls as more prioritized than `a.foo.invoke()`
|
||||
// It's not the same as TowerGroupKind because it's not about tower levels, but rather a different dimension semantically.
|
||||
// It could be implemented via another TowerGroupKind, but it's not clear what priority should be assigned to the new TowerGroupKind
|
||||
@@ -203,13 +206,23 @@ private constructor(
|
||||
}
|
||||
if (index < other.debugKinds.size) return -1
|
||||
|
||||
return invokeResolvePriority.compareTo(other.invokeResolvePriority)
|
||||
val actualResult = invokeResolvePriority.compareTo(other.invokeResolvePriority)
|
||||
if (actualResult == 0) {
|
||||
return if (receiverGroup == null || other.receiverGroup == null) 0
|
||||
else receiverGroup.debugCompareTo(other.receiverGroup)
|
||||
}
|
||||
return actualResult
|
||||
}
|
||||
|
||||
override fun compareTo(other: TowerGroup): Int = run {
|
||||
val result = java.lang.Long.compareUnsigned(code, other.code)
|
||||
if (result != 0) return@run result
|
||||
return@run invokeResolvePriority.compareTo(other.invokeResolvePriority)
|
||||
val actualResult = invokeResolvePriority.compareTo(other.invokeResolvePriority)
|
||||
if (actualResult == 0) {
|
||||
return@run if (receiverGroup == null || other.receiverGroup == null) 0
|
||||
else receiverGroup.compareTo(other.receiverGroup)
|
||||
}
|
||||
return@run actualResult
|
||||
}.also {
|
||||
if (DEBUG) {
|
||||
val debugResult = debugCompareTo(other)
|
||||
@@ -226,6 +239,9 @@ private constructor(
|
||||
if (code != other.code) return false
|
||||
if (DEBUG) require(this.debugKinds.contentEquals(other.debugKinds)) { "Equals inconsistent: $this vs $other" }
|
||||
if (invokeResolvePriority != other.invokeResolvePriority) return false
|
||||
if (receiverGroup != null && other.receiverGroup != null) {
|
||||
if (receiverGroup != other.receiverGroup) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user