[FIR] Fix resolution of objects in presence of low-priority candidates
For CallKind.VariableAccess, the condition when to *skip* resolution of objects was previously collector.isSuccess. This wasn't strict enough because collector.isSuccess could be true when the best found candidate has an applicability like RESOLVED_WITH_LOW_PRIORITY (e.g. from dynamic scope or annotated with @LowPriorityInOverloadResolution). In these cases, we do want to resolve objects. To fix this, the condition is changed to collector.shouldStopResolve which is stricter. #KT-57960 Fixed
This commit is contained in:
committed by
Space Team
parent
bc7aea1426
commit
8b47a4fa48
+6
@@ -39239,6 +39239,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/kt35210.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lowPriorityTopLevelValAndObject.kt")
|
||||
public void testLowPriorityTopLevelValAndObject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/lowPriorityTopLevelValAndObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("moreOnlyInputTypes.kt")
|
||||
public void testMoreOnlyInputTypes() throws Exception {
|
||||
|
||||
+6
@@ -39239,6 +39239,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/kt35210.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lowPriorityTopLevelValAndObject.kt")
|
||||
public void testLowPriorityTopLevelValAndObject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/lowPriorityTopLevelValAndObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("moreOnlyInputTypes.kt")
|
||||
public void testMoreOnlyInputTypes() throws Exception {
|
||||
|
||||
+6
@@ -39239,6 +39239,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/kt35210.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lowPriorityTopLevelValAndObject.kt")
|
||||
public void testLowPriorityTopLevelValAndObject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/lowPriorityTopLevelValAndObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("moreOnlyInputTypes.kt")
|
||||
public void testMoreOnlyInputTypes() throws Exception {
|
||||
|
||||
+6
@@ -39335,6 +39335,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/kt35210.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lowPriorityTopLevelValAndObject.kt")
|
||||
public void testLowPriorityTopLevelValAndObject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/lowPriorityTopLevelValAndObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("moreOnlyInputTypes.kt")
|
||||
public void testMoreOnlyInputTypes() throws Exception {
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ open class CandidateCollector(
|
||||
open fun shouldStopAtTheGroup(group: TowerGroup): Boolean =
|
||||
shouldStopResolve && bestGroup < group
|
||||
|
||||
private val shouldStopResolve: Boolean
|
||||
val shouldStopResolve: Boolean
|
||||
get() = currentApplicability.shouldStopResolve
|
||||
|
||||
val isSuccess: Boolean
|
||||
|
||||
+6
-1
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||
|
||||
internal class CandidateFactoriesAndCollectors(
|
||||
// Common calls
|
||||
@@ -45,7 +46,11 @@ internal class TowerLevelHandler {
|
||||
CallKind.VariableAccess -> {
|
||||
processResult += towerLevel.processPropertiesByName(info, processor)
|
||||
|
||||
if (!collector.isSuccess && towerLevel is ScopeTowerLevel && !towerLevel.areThereExtensionReceiverOptions()) {
|
||||
// Top-level properties win over objects. Therefore, if we find properties, we don't want to look for objects here.
|
||||
// However, this only applies if the best current candidate applicability has shouldStopResolve == true. Exceptions to this
|
||||
// are candidates from dynamic scopes or properties with @LowPriorityInOverloadResolution (from earlier or the same level),
|
||||
// therefore we check for collector.shouldStopResolve and not collector.isSuccess.
|
||||
if (!collector.shouldStopResolve && towerLevel is ScopeTowerLevel && !towerLevel.areThereExtensionReceiverOptions()) {
|
||||
processResult += towerLevel.processObjectsByName(info, processor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
FILE: kt57960.kt
|
||||
public final class Bar : R|kotlin/Any| {
|
||||
public constructor(): R|Bar| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final var toDOM: R|((Baz) -> kotlin/Any)?| = Null(null)
|
||||
public get(): R|((Baz) -> kotlin/Any)?|
|
||||
public set(value: R|((Baz) -> kotlin/Any)?|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public final class Baz : R|kotlin/Any| {
|
||||
public constructor(): R|Baz| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final var text: R|kotlin/String| = String()
|
||||
public get(): R|kotlin/String|
|
||||
public set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public final object Foo : R|kotlin/Any| {
|
||||
private constructor(): R|Foo| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun create2(toDOM: R|((Baz) -> kotlin/Any)?| = Null(null)): R|Bar| {
|
||||
^create2 R|/jso|<R|Bar|>(<L> = jso@fun R|Bar|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
|
||||
R|<local>/toDOM|?.{ $subj$.R|kotlin/let|<R|(Baz) -> kotlin/Any|, R|kotlin/Unit|>(<L> = let@fun <anonymous>(it: R|(Baz) -> kotlin/Any|): R|kotlin/Unit| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
this@R|special/anonymous|.R|/Bar.toDOM| = R|<local>/it|
|
||||
}
|
||||
) }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
private final fun buildSchemaNodes1(): R|kotlin/Unit| {
|
||||
R|/jso|<R|dynamic|>(<L> = jso@fun R|dynamic|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
|
||||
Q|Foo|.R|/Foo.create2|(toDOM = create2@fun <anonymous>(domNode: R|Baz|): R|kotlin/Any| <inline=NoInline> {
|
||||
^ R|<local>/domNode|.R|/Baz.text|
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
public final fun <T : R|kotlin/Any|> jso(): R|T| {
|
||||
^jso R|kotlin/js/js|(String(({})))
|
||||
}
|
||||
public final inline fun <T : R|kotlin/Any|> jso(block: R|T.() -> kotlin/Unit|): R|T| {
|
||||
^jso R|/jso|<R|T|>().R|kotlin/apply|<R|T|>(R|<local>/block|)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// FIR_IDENTICAL
|
||||
// FIR_DUMP
|
||||
// ISSUE: KT-57960
|
||||
|
||||
class Bar {
|
||||
var toDOM: ((Baz) -> Any)? = null
|
||||
}
|
||||
|
||||
class Baz {
|
||||
var text: String = ""
|
||||
}
|
||||
|
||||
object Foo {
|
||||
fun create2(
|
||||
toDOM: ((Baz) -> Any)? = null,
|
||||
) = jso<Bar> {
|
||||
toDOM?.let { this.toDOM = it }
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildSchemaNodes1() {
|
||||
jso<dynamic> {
|
||||
Foo.create2(toDOM = { domNode -> domNode.text })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun <T : Any> jso(): T =
|
||||
js("({})")
|
||||
|
||||
inline fun <T : Any> jso(
|
||||
block: T.() -> Unit,
|
||||
): T =
|
||||
jso<T>().apply(block)
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
FILE: objectAccessInLambdaWithDynamicReceiver.kt
|
||||
public final fun jso(block: R|dynamic.() -> kotlin/Unit|): R|dynamic| {
|
||||
^jso R|kotlin/js/js|(String(({}))).R|<dynamic>/apply|(vararg(R|<local>/block|))
|
||||
}
|
||||
public final class G : R|kotlin/Any| {
|
||||
public constructor(): R|G| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
private constructor(): R|G.Companion| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val foo: R|kotlin/String| = String(string)
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
R|/jso|(<L> = jso@fun R|dynamic|.<anonymous>(): R|kotlin/Unit| <inline=NoInline> {
|
||||
R|/G.G|()
|
||||
Q|G|.R|/G.Companion.foo|
|
||||
}
|
||||
)
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// FIR_IDENTICAL
|
||||
// FIR_DUMP
|
||||
|
||||
fun jso(block: dynamic.() -> Unit): dynamic = js("({})").apply(block)
|
||||
|
||||
class G {
|
||||
companion object {
|
||||
val foo = "string"
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
jso {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("G")!>G()<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>G.foo<!>
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// FIR_IDENTICAL
|
||||
// DIAGNOSTICS: -EXTENSION_SHADOWED_BY_MEMBER
|
||||
|
||||
// FILE: a.kt
|
||||
package a
|
||||
|
||||
val bar get() = ""
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@kotlin.internal.LowPriorityInOverloadResolution
|
||||
val baz get() = ""
|
||||
|
||||
// FILE: b.kt
|
||||
package b
|
||||
|
||||
object bar
|
||||
object baz {
|
||||
val qux = 1
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
import a.*
|
||||
import b.*
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
class Foo {
|
||||
@kotlin.internal.LowPriorityInOverloadResolution
|
||||
val bar = 1
|
||||
|
||||
@kotlin.internal.LowPriorityInOverloadResolution
|
||||
val baz = 1
|
||||
}
|
||||
|
||||
fun Foo.test() {
|
||||
bar.length
|
||||
baz.qux
|
||||
}
|
||||
Generated
+6
@@ -40107,6 +40107,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/kt35210.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lowPriorityTopLevelValAndObject.kt")
|
||||
public void testLowPriorityTopLevelValAndObject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/lowPriorityTopLevelValAndObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("moreOnlyInputTypes.kt")
|
||||
public void testMoreOnlyInputTypes() throws Exception {
|
||||
|
||||
+12
@@ -289,6 +289,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt57960.kt")
|
||||
public void testKt57960() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/kt57960.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("membersOfAny.kt")
|
||||
public void testMembersOfAny() throws Exception {
|
||||
@@ -313,6 +319,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/nullable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("objectAccessInLambdaWithDynamicReceiver.kt")
|
||||
public void testObjectAccessInLambdaWithDynamicReceiver() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/objectAccessInLambdaWithDynamicReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overloading.kt")
|
||||
public void testOverloading() throws Exception {
|
||||
|
||||
+12
@@ -290,6 +290,12 @@ public class FirPsiJsOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiJ
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt57960.kt")
|
||||
public void testKt57960() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/kt57960.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("membersOfAny.kt")
|
||||
public void testMembersOfAny() throws Exception {
|
||||
@@ -314,6 +320,12 @@ public class FirPsiJsOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiJ
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/nullable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("objectAccessInLambdaWithDynamicReceiver.kt")
|
||||
public void testObjectAccessInLambdaWithDynamicReceiver() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/objectAccessInLambdaWithDynamicReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overloading.kt")
|
||||
public void testOverloading() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user